Questioning Everything Propaganda

Home Tags
Login RSS
BXC Benford Fraud Analysis
You are viewing an old revision from 2026-01-15 07:06.
View the current, live version.

error tho file there

/* REXX */
/* ========================================================================== */
/* BXC - Benford Analysis Tool (Classic REXX for ArcaOS 5.1.1)              */
/* Original BASIC version by Jason S. Page                                   */
/* Enhanced Classic REXX version for ArcaOS                                  */
/* ========================================================================== */

/* -------------------------------------------------------------------------- */
/* Robust RexxUtil Loading for ArcaOS 5.1.1                                  */
/* -------------------------------------------------------------------------- */
call LoadRexxUtil

/* -------------------------------------------------------------------------- */
/* Initialize Benford's Law Constants                                        */
/* -------------------------------------------------------------------------- */
numeric digits 12

benford.0 = 9
benford.1 = 30.1
benford.2 = 17.6
benford.3 = 12.5
benford.4 = 9.7
benford.5 = 7.9
benford.6 = 6.7
benford.7 = 5.8
benford.8 = 5.1
benford.9 = 4.6

/* -------------------------------------------------------------------------- */
/* Initialize Global Variables                                               */
/* -------------------------------------------------------------------------- */
toke = 0
animate = 0
animate_interval = 100
total_processed = 0
block_char = 'DB'x

/* -------------------------------------------------------------------------- */
/* Parse Command Line Arguments                                              */
/* -------------------------------------------------------------------------- */
parse arg params

load1 = ""
a12 = ""
prog = ""
col = ""
anim = ""

call ParseFlag "-f", params
load1 = result

call ParseFlag "-d", params
a12 = result

call ParseFlag "-l", params
prog = result

call ParseFlag "-c", params
col = result

call ParseFlag "-a", params
anim = result

/* -------------------------------------------------------------------------- */
/* Show Help if Requested                                                    */
/* -------------------------------------------------------------------------- */
if pos("-h", params) > 0 | pos("--help", params) > 0 then do
    call ShowHelp
    exit
end

/* -------------------------------------------------------------------------- */
/* Handle Animation Flag                                                     */
/* -------------------------------------------------------------------------- */
if length(anim) > 0 then do
    animate = 1
    if datatype(anim, 'W') then animate_interval = anim
end

/* -------------------------------------------------------------------------- */
/* Interactive Mode if Missing Required Arguments                            */
/* -------------------------------------------------------------------------- */
if length(load1) = 0 | length(a12) = 0 | length(prog) = 0 | length(col) = 0 then do
    say "Error: Missing required flags."
    say ""
    say "Interactive mode:"

    call SysFileTree "*.dat", "fileList", "FO"
    do i = 1 to fileList.0
        say "Found: " || fileList.i
    end

    call charout , "Load file: "
    parse pull load1

    call charout , "[A]ll Digits or [1]st Digit: "
    parse pull a12

    call charout , "Capture Average Every (default: 10000) Points: "
    parse pull prog

    call charout , "Which Column Number (0 = single column): "
    parse pull col

    call charout , "Enable animation? [y/n]: "
    parse pull anim_choice

    if translate(left(anim_choice, 1)) = "Y" then do
        animate = 1
        call charout , "Update interval (default: 100): "
        parse pull anim_input
        if datatype(anim_input, 'W') then animate_interval = anim_input
    end
end

/* -------------------------------------------------------------------------- */
/* Set Defaults                                                              */
/* -------------------------------------------------------------------------- */
if length(prog) = 0 then prog = "10000"
if length(col) = 0 then col = "0"
if col = "0" then col = "1"

/* -------------------------------------------------------------------------- */
/* Display Configuration                                                     */
/* -------------------------------------------------------------------------- */
say ""
say "Configuration:"
say "  File: " || load1
say "  Digits: " || a12
say "  Sample size: " || prog
say "  Column: " || col
if animate = 1 then
    say "  Animation: Enabled (update every " || animate_interval || " records)"
else
    say "  Animation: Disabled"
say ""

/* -------------------------------------------------------------------------- */
/* Download File if URL                                                      */
/* -------------------------------------------------------------------------- */
if left(translate(load1), 3) = "FTP" | left(translate(load1), 4) = "HTTP" then do
    say "Downloading file..."
    address CMD "wget -c " || load1 || " 2>&1"

    last_slash = lastpos('/', load1)
    if last_slash > 0 then load1 = substr(load1, last_slash + 1)

    say "Assuming downloaded file is: " || load1
end

/* -------------------------------------------------------------------------- */
/* Verify File Exists                                                        */
/* -------------------------------------------------------------------------- */
if \SysFileExists(load1) then do
    say "Error: File '" || load1 || "' not found!"
    exit 1
end

/* -------------------------------------------------------------------------- */
/* Create Log Files                                                          */
/* -------------------------------------------------------------------------- */
log_values = load1 || "_" || a12 || "-" || prog || "-.log"
log_percent = load1 || "_" || a12 || "-" || prog || "_.log"

call lineout log_values, , 1
call lineout log_percent, , 1

/* -------------------------------------------------------------------------- */
/* Initialize Counters                                                       */
/* -------------------------------------------------------------------------- */
c. = 0
count_total = 0

/* -------------------------------------------------------------------------- */
/* Display Header                                                            */
/* -------------------------------------------------------------------------- */
say ""
say "========================================================================"
say "Benford X-C Forensics Digital Analysis Tool (ArcaOS 5.1.1)"
say "========================================================================"
say ""

if animate = 0 then do
    say "    Record,  1,  2,  3,  4,  5,  6,  7,  8,  9"
end

/* -------------------------------------------------------------------------- */
/* Main Processing Loop                                                      */
/* -------------------------------------------------------------------------- */
infile = load1

do while lines(infile) > 0
    line = linein(infile)
    toke = toke + 1
    total_processed = total_processed + 1

    if length(line) = 0 then iterate

    ot = line

    /* Extract column if needed */
    if col > 1 then do
        call ExtractColumn line, col
        ot = result
    end

    /* Clean to digits only */
    call ExtractDigits ot
    ot = result

    if length(ot) = 0 then iterate

    /* Determine position based on digit mode */
    if translate(left(a12, 1)) = "A" then
        position = length(ot)
    else
        position = 1

    /* Count digits */
    do i = 1 to position
        digit = substr(ot, i, 1)
        if digit >= 1 & digit <= 9 then do
            count_total = count_total + 1
            c.digit = c.digit + 1
        end
    end

    /* Animate if enabled */
    if animate = 1 & (total_processed // animate_interval = 0) & count_total > 0 then do
        call DrawAnimatedChart count_total, total_processed, prog
    end

    /* Write sample when reaching sample size */
    if count_total >= prog then do
        p. = 0
        do i = 1 to 9
            if count_total > 0 then
                p.i = format((c.i * 100) / count_total, 2, 2)
            else
                p.i = 0
        end

        cc1 = ot || "," || toke || "," || c.1 || "," || c.2 || "," || c.3 || "," || c.4 || "," || c.5 || "," || c.6 || "," || c.7 || "," || c.8 || "," || c.9
        cc2 = ot || "," || toke || "," || p.1 || "," || p.2 || "," || p.3 || "," || p.4 || "," || p.5 || "," || p.6 || "," || p.7 || "," || p.8 || "," || p.9

        if animate = 0 then do
            say "#: " || cc1
            say "%: " || cc2
        end

        call lineout log_values, cc1
        call lineout log_percent, cc2

        /* Reset counters */
        count_total = 0
        do i = 1 to 9
            c.i = 0
        end
    end
end

/* -------------------------------------------------------------------------- */
/* Close Files                                                               */
/* -------------------------------------------------------------------------- */
call stream infile, 'C', 'CLOSE'
call lineout log_values
call lineout log_percent

if animate = 1 then say ""

/* -------------------------------------------------------------------------- */
/* Display Completion Message                                                */
/* -------------------------------------------------------------------------- */
say ""
say "========================================================================"
say "Analysis Complete"
say "========================================================================"
say "Total records processed: " || toke
say ""

say "Calculating final statistics and chi-squared test..."
call GenerateFinalReport log_percent, load1, a12, prog

say ""
say "Output files:"
say "  Values log: " || log_values
say "  Percent log: " || log_percent
say ""

exit 0

/* ========================================================================== */
/* Subroutines                                                               */
/* ========================================================================== */

/* -------------------------------------------------------------------------- */
/* ShowHelp - Display usage information                                      */
/* -------------------------------------------------------------------------- */
ShowHelp:
    say "=================================="
    say "bxc - Benford Analysis Tool (ArcaOS)"
    say "=================================="
    say "Usage: bxc -f [file] -d [1|all] -l [length] -c [column] -a [interval]"
    say ""
    say "Required flags:"
    say "  -f [file]      Data file to analyze (or URL)"
    say "  -d [1|all]     Analyze first digit (1) or all digits (all)"
    say "  -l [number]    Sample pool length (default: 10000)"
    say "  -c [number]    Column number (0 for single column)"
    say ""
    say "Optional flags:"
    say "  -a [interval]  Enable animated graph (default: 100)"
    say "  -h, --help     Show this help message"
    say ""
    say "Example:"
    say "  bxc -f data.dat -d 1 -l 10000 -c 1"
    return

/* -------------------------------------------------------------------------- */
/* ParseFlag - Extract flag value from command line                          */
/* -------------------------------------------------------------------------- */
ParseFlag: procedure
    parse arg flag, cmdline
    result = ""
    ppos = pos(flag, cmdline)
    if ppos > 0 then do
        start = ppos + length(flag) + 1
        rest = substr(cmdline, start)
        parse var rest val " -" rest_ignored
        result = strip(val)
    end
    return result

/* -------------------------------------------------------------------------- */
/* ExtractColumn - Extract specified column from CSV line                    */
/* -------------------------------------------------------------------------- */
ExtractColumn: procedure
    parse arg line, col_num

    if col_num <= 1 then return line

    loop_col = 1
    temp_line = line
    found_val = ""

    do while loop_col <= col_num
        parse var temp_line this_val "," temp_line
        if loop_col = col_num then found_val = this_val
        loop_col = loop_col + 1
    end

    return found_val

/* -------------------------------------------------------------------------- */
/* ExtractDigits - Extract only numeric digits from string                   */
/* -------------------------------------------------------------------------- */
ExtractDigits: procedure
    parse arg text

    clean = ""
    do i = 1 to length(text)
        char = substr(text, i, 1)
        if datatype(char, 'N') then clean = clean || char
    end

    return clean

/* -------------------------------------------------------------------------- */
/* DrawAnimatedChart - Display live animated chart                           */
/* -------------------------------------------------------------------------- */
DrawAnimatedChart: procedure expose c. benford. block_char
    parse arg total_seg, total_proc, sample_size

    call SysCls

    say "========================================================================"
    say "Benford X-C Live Analysis - Animated View"
    say "========================================================================"
    say "Processing: " || total_proc || " records | Sample pool: " || sample_size || " | Current: " || total_seg
    say "------------------------------------------------------------------------"
    say ""
    say "Digit  Actual   Expected  Deviation  Chart"
    say "-----  -------  --------  ---------  ---------------------------------"

    do i = 1 to 9
        if total_seg > 0 then
            pct = (c.i * 100) / total_seg
        else
            pct = 0
        call PrintDigitRow i, pct, benford.i
    end

    say "========================================================================"
    return

/* -------------------------------------------------------------------------- */
/* PrintDigitRow - Display single digit row in chart                         */
/* -------------------------------------------------------------------------- */
PrintDigitRow: procedure expose block_char
    parse arg digit, actual, expected

    deviation = actual - expected
    bar_len = actual / 2
    if bar_len > 50 then bar_len = 50

    bar = copies(block_char, trunc(bar_len))

    s_actual = format(actual, 2, 1) || "%"
    s_expect = format(expected, 2, 1) || "%"

    sign = " "
    if deviation >= 0 then sign = "+"
    s_dev = sign || format(deviation, 2, 1) || "%"

    say "  " || digit || "    " || left(s_actual, 7) || "  " || left(s_expect, 8) || "  " || left(s_dev, 9) || "  " || bar
    return

/* -------------------------------------------------------------------------- */
/* GenerateFinalReport - Create final statistical report                     */
/* -------------------------------------------------------------------------- */
GenerateFinalReport: procedure expose benford. block_char
    parse arg percent_file, data_file, mode, samp

    sum. = 0
    count = 0

    /* Check if file exists and has content */
    if \SysFileExists(percent_file) then return

    /* Read and calculate averages */
    call stream percent_file, 'C', 'CLOSE'

    do while lines(percent_file) > 0
        line = linein(percent_file)
        if length(line) = 0 then iterate

        parse var line toss "," recd "," p.1 "," p.2 "," p.3 "," p.4 "," p.5 "," p.6 "," p.7 "," p.8 "," p.9

        do i = 1 to 9
            sum.i = sum.i + p.i
        end
        count = count + 1
    end
    call stream percent_file, 'C', 'CLOSE'

    if count > 0 then do
        chi_squared = 0

        say "Final Statistics (Averaged across all samples):"
        say "------------------------------------------------"
        say "Digit  Actual   Expected  Deviation"
        say "-----  -------  --------  ---------"

        do i = 1 to 9
            avg = sum.i / count
            dev = avg - benford.i
            chi_part = (dev * dev) / benford.i
            chi_squared = chi_squared + chi_part

            s_avg = format(avg, 2, 1) || "%"
            s_exp = format(benford.i, 2, 1) || "%"
            s_dev = format(dev, 2, 1) || "%"

            say "  " || i || "    " || left(s_avg, 7) || "  " || left(s_exp, 8) || "  " || s_dev
        end

        say ""
        say "Chi-Squared Statistic: " || format(chi_squared, 4, 4)
        say ""

        /* Interpret results */
        if chi_squared < 15.51 then do
            say "Result: Data FITS Benford's Law (95% confidence)"
            say "        No significant deviation detected."
        end
        else do
            say "Result: Data DOES NOT fit Benford's Law (95% confidence)"
            say "        Significant deviation detected - possible fraud indicator!"
        end

        say ""
        say "Generating ASCII chart..."
        call GenerateChart percent_file
    end
    return

/* -------------------------------------------------------------------------- */
/* GenerateChart - Create ASCII chart output file                            */
/* -------------------------------------------------------------------------- */
GenerateChart: procedure expose block_char
    parse arg percent_file

    chart_file = "chart_" || percent_file || ".txt"

    call lineout chart_file, , 1

    call stream percent_file, 'C', 'CLOSE'
    sample_count = 0

    do while lines(percent_file) > 0
        line = linein(percent_file)
        if length(line) = 0 then iterate

        parse var line toss "," recd "," p.1 "," p.2 "," p.3 "," p.4 "," p.5 "," p.6 "," p.7 "," p.8 "," p.9

        sample_count = sample_count + 1
        call lineout chart_file, "========================================================================"
        call lineout chart_file, "Sample #" || sample_count || " | Record: " || recd || " | Value: " || toss
        call lineout chart_file, "------------------------------------------------------------------------"

        do i = 1 to 9
            call WriteChartLine chart_file, i, p.i
        end
        call lineout chart_file, ""
    end

    call stream percent_file, 'C', 'CLOSE'
    call stream chart_file, 'C', 'CLOSE'

    say "ASCII chart saved to: " || chart_file
    say ""
    say "Preview (first sample):"
    call DisplayHead chart_file, 15
    say ""
    say "Preview (last sample):"
    call DisplayTail chart_file, 12
    return

/* -------------------------------------------------------------------------- */
/* WriteChartLine - Write single chart line to file                          */
/* -------------------------------------------------------------------------- */
WriteChartLine: procedure expose block_char
    parse arg file_name, digit, percentage

    bar_len = percentage
    if bar_len > 100 then bar_len = 100

    bar = copies(digit, trunc(bar_len))

    line = "  " || digit || " | " || format(percentage, 2, 1) || "% | " || bar
    call lineout file_name, line
    return

/* -------------------------------------------------------------------------- */
/* DisplayHead - Display first N lines of file                               */
/* -------------------------------------------------------------------------- */
DisplayHead: procedure
    parse arg file, num_lines

    cnt = 0
    call stream file, 'C', 'CLOSE'

    do while lines(file) > 0 & cnt < num_lines
        say linein(file)
        cnt = cnt + 1
    end

    call stream file, 'C', 'CLOSE'
    return

/* -------------------------------------------------------------------------- */
/* DisplayTail - Display last N lines of file                                */
/* -------------------------------------------------------------------------- */
DisplayTail: procedure
    parse arg file, num_lines

    /* Read entire file into stem */
    call stream file, 'C', 'CLOSE'

    fileContent.0 = 0
    do while lines(file) > 0
        idx = fileContent.0 + 1
        fileContent.idx = linein(file)
        fileContent.0 = idx
    end

    call stream file, 'C', 'CLOSE'

    /* Display last N lines */
    start_line = fileContent.0 - num_lines + 1
    if start_line < 1 then start_line = 1

    do i = start_line to fileContent.0
        say fileContent.i
    end
    return

/* -------------------------------------------------------------------------- */
/* LoadRexxUtil - Load RexxUtil functions for ArcaOS 5.1.1                  */
/* -------------------------------------------------------------------------- */
LoadRexxUtil:
    /* Try different RexxUtil loading methods for ArcaOS compatibility */

    /* Method 1: Check if already loaded (ArcaOS often preloads) */
    if RxFuncQuery('SysFileExists') = 0 then do
        /* Already loaded */
        return
    end

    /* Method 2: Try loading from REXXUTIL (uppercase) */
    signal on syntax name RexxUtilError
    call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs'
    call SysLoadFuncs
    signal off syntax

    /* Verify it loaded */
    if RxFuncQuery('SysFileExists') = 0 then return

    /* Method 3: Try loading from RexxUtil (mixed case) */
    signal on syntax name RexxUtilError
    call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
    call SysLoadFuncs
    signal off syntax

    /* Verify it loaded */
    if RxFuncQuery('SysFileExists') = 0 then return

    /* Method 4: Try loading from rexxutil (lowercase) - ArcaOS 5.1.1 */
    signal on syntax name RexxUtilError
    call RxFuncAdd 'SysLoadFuncs', 'rexxutil', 'SysLoadFuncs'
    call SysLoadFuncs
    signal off syntax

    /* Verify it loaded */
    if RxFuncQuery('SysFileExists') = 0 then return

    /* If we get here, loading failed */
    say ""
    say "========================================================================"
    say "ERROR: Could not load RexxUtil functions"
    say "========================================================================"
    say ""
    say "This script requires RexxUtil (rexxutil.dll) to be available."
    say ""
    say "Troubleshooting steps:"
    say "  1. Verify rexxutil.dll exists in your LIBPATH"
    say "  2. Check: DIR rexxutil.dll in your OS/2 directory"
    say "  3. On ArcaOS 5.1.1, this should be in C:\OS2\DLL"
    say "  4. Try: SET LIBPATH | FIND /I \"DLL\""
    say ""
    say "Alternative: Use bxc_benford_minimal.cmd which doesn't need RexxUtil"
    say ""
    exit 99

RexxUtilError:
    /* Silently continue to next method */
    signal off syntax
    return


Original Author: admin

Views: 255 (Unique: 231)

Page ID ( Copy Link): page_6923db566fd807.22535029-4870ac84de8bbc87

Page History (9 revisions):