Revised Code for Radioactivity Simulation With Improved Algorithm v0.02

output2I revised the algorithm that the program uses to calculate event times to more closely fit the exponential decay function.  As can be seen in the chart of the new simulated output above, the original program was off by a factor exceeding 100 for the average energy output in the first 20 minutes.  The change in the code did slow the calculations significantly, but correcting this source of error near the beginning and end of each half-life was crucial so that peak radiation levels can be accounted for.

Here is the revised Event.java code:

package Radioactivity;

public class Event {
    // An Event calculates and contains one radiative event 
    /* Variable and Function Nomenclature prescripts:
     * pv = private
     * pu = public
     * pvs = private static
     * pus = public static
     * pvsf = private static final
     * pusf = public static final
     */
    private double pvTime = 0.0; //calculated time of the event referenced from arbitrary start point in seconds 
    private double pvEnergy = 0.0; //user supplied event energy in MeV
    private String pvType; //user supplied event type (alpha, beta, gamma, neutron)
    private double pvHalfLife =0.0; //user supplied event half-life in seconds
    private int pvMaxHalfLives = 20;
    private double pvTimeOffset = 0.0; //user supplied offset time in seconds
    //pvDetailedTest is a predefined seive to reduce error in the time calculation
    private int pvDetailedTest[] = {
            1077,2143,3197,4240,
            5271,6292,7301,8300,
            9287,10265,11231,12187,
            13133,14069,14995,15910,
            16816,17712,18599,19475,
            20343,21201,22050,22889,
            23720,24542,25355,26159,
            26954,27741,28519,29289,
            30051,30805,31550,32287,
            33017,33738,34452,35158,
            35856,36547,37231,37907,
            38576,39238,39892,40540,
            41180,41814,42441,43061,
            43674,44281,44881,45475,
            46062,46643,47218,47786,
            48349,48905,49456,50000};    
    public Event(double halfLife, double energy, String type) {
        if (energy > 0) {
            pvEnergy = energy;
        } else {
            System.out.println("(Event) construction failed because (Event) input (energy) must be a positive number and greater than zero");
        }
        pvType = type;
        if (halfLife > 0) {
            pvHalfLife = halfLife;
        } else {
            System.out.println("(Event) construction failed because input (halflife) must be a positive number and greater than zero");
        }
        if (pvHalfLife > 0) {
            pvTime = pvCalcTime();
        } else {
            System.out.println("(Event) construction failed because (pvTime) cannot be calculated without a defined (halflife)");
        }
        pvMaxHalfLives = 20;
        pvTimeOffset = 0.0;
    }
    public Event(double halfLife, double energy, String type,double timeOffset) {
        if (timeOffset > 0) {
            pvTimeOffset = timeOffset;
        } else {
            System.out.println("(Event) construction failed because (timeOffset) input must be a positive number and greater than zero");
        }
        if (energy > 0) {
            pvEnergy = energy;
        } else {
            System.out.println("(Event) construction failed because (Event) input (energy) must be a positive number and greater than zero");
        }
        pvType = type;
        if (halfLife > 0) {
            pvHalfLife = halfLife;
        } else {
            System.out.println("(Event) construction failed because input (halflife) must be a positive number and greater than zero");
        }
        if (pvHalfLife > 0) {
            pvTime = pvCalcTime();
        } else {
            System.out.println("(Event) construction failed because (pvTime) cannot be calculated without a defined (halflife)");
        }
        pvMaxHalfLives = 20;
    }
    public Event(double halfLife, double energy, String type, int maxHalfLives) {
        if (energy > 0) {
            pvEnergy = energy;
        } else {
            System.out.println("(Event) construction failed because (Event) input (energy) must be a positive number and greater than zero");
        }
        pvType = type;
        if (halfLife > 0) {
            pvHalfLife = halfLife;
        } else {
            System.out.println("(Event) construction failed because input (halflife) must be a positive number and greater than zero");
        }
        if (maxHalfLives > 0) {
            pvMaxHalfLives = maxHalfLives;
        } else {
            System.out.println("Using default (pvMaxHalfLives) of 20 because the (maxHalfLives) supplied to the constructor was not a positive number and greater than zero");
            pvMaxHalfLives = 20;
        }
        if (pvHalfLife > 0) {
            pvTime = pvCalcTime();
        } else {
            System.out.println("(Event) construction failed because (pvTime) cannot be calculated without a defined (halflife)");
        }
        pvTimeOffset = 0.0;
        
    }
    public Event(double halfLife, double energy, String type,double timeOffset, int maxHalfLives) {
        if (timeOffset > 0) {
            pvTimeOffset = timeOffset;
        } else {
            System.out.println("(Event) construction failed because (timeOffset) input must be a positive number and greater than zero");
        }
        if (energy > 0) {
            pvEnergy = energy;
        } else {
            System.out.println("(Event) construction failed because (Event) input (energy) must be a positive number and greater than zero");
        }
        pvType = type;
        if (halfLife > 0) {
            pvHalfLife = halfLife;
        } else {
            System.out.println("(Event) construction failed because input (halflife) must be a positive number and greater than zero");
        }
        if (maxHalfLives > 0) {
            pvMaxHalfLives = maxHalfLives;
        } else {
            System.out.println("Using default (pvMaxHalfLives) of 20 because the (maxHalfLives) supplied to the constructor was not a positive number and greater than zero");
            pvMaxHalfLives = 20;
        }
        if (pvHalfLife > 0) {
            pvTime = pvCalcTime();
        } else {
            System.out.println("(Event) construction failed because (pvTime) cannot be calculated without a defined (halflife)");
        }

    }
    private double pvCalcTime() {
        double seed1 = Math.random();
        double seed2 = Math.random();
        double seed3 = Math.random();
        double weightedLife = Math.pow(2,pvMaxHalfLives);
        double testWeightedLife = seed1 * weightedLife;
        double testDetailedLife = seed2 * 50000;
        double t = 0;
        int x = 0;
        while (t == 0) {
            if (x == (pvMaxHalfLives-1)) {
                for (int y = 0; y<64;y++) {
                    if (testDetailedLife <= pvDetailedTest[y]){
                        t = (x+y/64+seed3/64)*pvHalfLife;
                    }
                }
            } else if (testWeightedLife <= weightedLife*(1+(x*2))/Math.pow(2,x+1)){
                for (int y = 0; y<64;y++) {
                    if (testDetailedLife <= pvDetailedTest[y]){
                        t = (x+y/64+seed3/64)*pvHalfLife;
                    }
                }
            }
            x+=1;
        }    
        return (t+pvTimeOffset);
    }
    public double puGetTime() {
        if (pvTime > 0) {    
            return pvTime;
        } else {
            System.out.println("(puGetTime) failed because this (Event) does not have a calculated (pvTime)");
            return 0;
        }
    }
    public double puGetHalfLife() {
        if (pvHalfLife > 0) {    
            return pvHalfLife;
        } else {
            System.out.println("(puGetHalfLife) failed because this (Event) does not have a proper (pvHalflife) assigned");
            return 0;
        }
    }
    public String puGetType() {
        return pvType;
    }
    public double puGetEnergy() {
        if (pvEnergy > 0) {    
            return pvEnergy;
        } else {
            System.out.println("(puGetEnergy) failed because this (Event) does not have a proper (pvEnergy) assigned");
            return 0;
        }
    }
    public void puSetHalfLife(double halflife) {
        if (halflife > 0) {    
            pvHalfLife = halflife;
        } else {
            System.out.println("(puSetHalfLife) failed because the (halflife) provided is not greater than zero");
            pvHalfLife = 0;
        }
    }
    public void puSetHalfLife(double halflife, int maxhalflives) {
        if (halflife > 0) {    
            pvHalfLife = halflife;
            if (maxhalflives > 0) {
                pvMaxHalfLives = maxhalflives;
                pvTime = pvCalcTime();
            } else {
                System.out.println("(puSetHalfLife) failed because the (maxhalflives) provided is not greater than zero");
                pvMaxHalfLives = 0;
                pvTime = 0.0;
            }
        } else {
            System.out.println("(puSetHalfLife) failed because the (halflife) provided is not greater than zero");
            pvHalfLife = 0;
        }
    }
    public void puSetType(String newtype) {
        pvType = newtype;
    }
    public void puSetEnergy(double energy) {
        if (energy > 0) {    
            pvEnergy = energy;
        } else {
            System.out.println("(puSetEnergy) failed because the (energy) provided is not greater than zero");
            pvEnergy = 0;
        }
    }
}

Rudimentary Code for Radioactivity Simulation v0.01

I took the day and wrote up some code to generate simulated radiation events based on some previously theorized decay chains. The Event and decay chain data were taken from the Thorium series section of the https://en.wikipedia.org/wiki/Decay_chains website. This is a proof of concept for the computational logic rather than a final product, so there are things that can and should be done such as reading the decay chain data off of input files rather than hard coding it, and many more data output options should be added.

Anyway, here is a simulation of the first hour of events from a pure sample of 100,000 RA-224 nuclei:

Chart

Does the code work? It seems to work but I have not compared it to any real data. It’s certainly got advantages over handling the real deal.  The algorithm used to calculate the time for each decay is likely to result in errors in the key regions at the beginnings and end of each half-life.  This is especially problematic when considering the first part of the first half life, as that will be the time in which the most heat energy would be expected to be produced. This algorithm will need to be improved.  The program is divided into four parts, here is the code:

First is DataExport.java

package Radioactivity;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class DataExport {

    public static void main(String[] args) {
        RA224 test = new RA224(100000);
        double[][] data = test.puGetEnergyAndTime();
        for (int x = 0; x < data.length;x++) {
            scribe(Double.toString(data[x][0]) + " " + Double.toString(data[x][1]));
        }
    }
    private static void scribe(String textline) {
        PrintWriter writer = null;
        BufferedWriter bw = null;
        FileWriter fw = null;
        try {
            fw = new FileWriter("/home/user/workspace/Radioactivity/output/out.txt",true);
            bw = new BufferedWriter(fw);
            writer = new PrintWriter(bw);
            writer.println(textline);
            
        } catch (IOException ex) {
            System.out.println(ex);
        } finally {
            try {writer.close();} catch (Exception ex) {}
        }
    }

}

Next is RA224.java which contains the decay chain logic

package Radioactivity;

public class RA224 {
    // a group of partNum ra224 nuclei whose radioactive Events are calculated for maxYears
    /* Variable and Function Nomenclature Prescipts:
     * pv = private
     * pu = public
     * pvs = private static
     * pus = public static
     * pvsf = private static final
     * pusf = public static final
     */
    
    private int pvPartNum = 0;
    private Event[] pvEvents;
    public RA224(int num) {
        if (num > 0) {
            pvPartNum = num;
            pvEvents = new Event[pvPartNum*6];
            eventCalc();
        } else {
            System.out.println("Construction of this (RA224) failed because the (num) supplied was not greater than zero");
            pvPartNum = 0;
        }
    }
    private void eventCalc() {
        for(int x = 0; x<pvPartNum; x++) {
            //ra224 to rn220
            //type = alpha
            //energy = 5.789 MeV
            //halflife = 3.6319 days
            String type = "alpha";
            double energy = 5.789;
            double halflife = 24*60*60*3.6319;
            pvEvents[x] = new Event(halflife,energy,type);
        }
        for(int x = 0; x<pvPartNum; x++) {
            //rn220 to po216
            //type = alpha
            //energy = 6.404 MeV
            //halflife = 55.6 seconds
            String type = "alpha";
            double energy = 6.404;
            double halflife = 55.6;
            pvEvents[x+pvPartNum] = new Event(halflife,energy,type,pvEvents[x].puGetTime());
        }
        for(int x = 0; x<pvPartNum; x++) {
            //po216 to pb212
            //type = alpha
            //energy = 6.906 MeV
            //halflife = 0.145 seconds
            String type = "alpha";
            double energy = 6.906;
            double halflife = 0.145;
            pvEvents[x+2*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+pvPartNum].puGetTime());
        }
        for(int x = 0; x<pvPartNum; x++) {
            //pb212 to bi212
            //type = beta-
            //energy = 0.570
            //halflife = 10.64 hours
            String type = "beta-";
            double energy = 0.570;
            double halflife = 60*60*10.64;
            pvEvents[x+3*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+2*pvPartNum].puGetTime());
        }
        int numPO212 = Math.toIntExact(Math.round(Math.random()*pvPartNum)); 
        int numTI208 = pvPartNum - numPO212;
        //bi212 to either po212 or ti208
        //po212 type = beta-
        //ti208 type = alpha
        //po212 energy = 2.252 MeV
        //ti208 energy = 6.208 MeV
        //po212 halflife = 60.55 min
        //ti208 halflife = 60.55 min
        for(int x=0;x<numPO212;x++){
            String type = "beta-";
            double energy = 2.252;
            double halflife = 60*60.55;
            pvEvents[x+4*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+3*pvPartNum].puGetTime());
        }
        for(int x=0;x<numTI208;x++){
            String type = "alpha";
            double energy = 6.208;
            double halflife = 60*60.55;
            pvEvents[x+4*pvPartNum+numPO212] = new Event(halflife,energy,type,pvEvents[x+3*pvPartNum+numPO212].puGetTime());
        }
        
        for(int x = 0; x<numPO212; x++) {
            //po212 to pb208
            //type = alpha
            //energy = 8.955 MeV
            //halflife = 299 ns
            String type = "alpha";
            double energy = 8.955;
            double halflife = 299*Math.pow(10,-9);
            pvEvents[x+5*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+4*pvPartNum].puGetTime());
        }
        for(int x = 0; x<numTI208; x++) {
            //po212 to pb208
            //type = beta-
            //energy = 4.999 MeV
            //halflife = 3.053 min
            String type = "beta-";
            double energy = 4.999;
            double halflife = 60*3.053;
            pvEvents[x+5*pvPartNum+numPO212] = new Event(halflife,energy,type,pvEvents[x+4*pvPartNum+numPO212].puGetTime());    
        }
    }
    public double[][] puGetEnergyAndTime() {
        double returned[][] = new double[pvPartNum*6][2];
        for (int x = 0;x<pvPartNum*6;x++) {
            returned[x][0]=pvEvents[x].puGetTime();
            returned[x][1]=pvEvents[x].puGetEnergy();
        }
        return returned;
    }

}

Next is TH232.java with decay logic for that nuclei (not used)

package Radioactivity;

public class TH232 {
    // a group of partNum th232 nuclei whose radioactive Events are calculated for maxYears
    /* Variable and Function Nomenclature Prescipts:
     * pv = private
     * pu = public
     * pvs = private static
     * pus = public static
     * pvsf = private static final
     * pusf = public static final
     */
    
    private int pvPartNum = 0;
    private Event[] pvEvents;
    public TH232(int num) {
        if (num > 0) {
            pvPartNum = num;
            pvEvents = new Event[pvPartNum*10];
            eventCalc();
        } else {
            System.out.println("Construction of this (TH232) failed because the (num) supplied was not greater than zero");
            pvPartNum = 0;
        }
    }
    private void eventCalc() {
        for(int x = 0; x<pvPartNum; x++) {
            //th232 to ra228
            //type = alpha
            //energy = 4.081 MeV
            //halflife = 1.405 * 10^10 years
            String type = "alpha";
            double energy = 4.081;
            double halflife = 365*24*60*60*1.405*Math.pow(10,10);
            pvEvents[x] = new Event(halflife,energy,type);            
        }
        for(int x = 0; x<pvPartNum; x++) {
            //ra228 to ac228    
            //type = beta-
            //energy = 0.046 MeV
            //halflife = 5.75 years
            String type = "beta-";
            double energy = 0.046;
            double halflife = 365*24*60*60*5.75;
            pvEvents[x+pvPartNum] = new Event(halflife,energy,type,pvEvents[x].puGetTime());
        }
        for(int x = 0; x<pvPartNum; x++) {
            //ac228 to th228
            //type = beta-
            //energy = 2.124 MeV
            //halflife = 6.35 hours
            String type = "beta-";
            double energy = 2.124;
            double halflife = 60*60*6.35;
            pvEvents[x+2*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+pvPartNum].puGetTime());
        }
        for(int x = 0; x<pvPartNum; x++) {
            //th228 to ra224
            //type = alpha
            //energy = 5.520 MeV
            //halflife = 1.9116 years
            String type = "alpha";
            double energy = 5.520;
            double halflife = 365*24*60*60*1.9116;
            pvEvents[x+3*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+2*pvPartNum].puGetTime());
        }
        for(int x = 0; x<pvPartNum; x++) {
            //ra224 to rn220
            //type = alpha
            //energy = 5.789 MeV
            //halflife = 3.6319 days
            String type = "alpha";
            double energy = 5.789;
            double halflife = 24*60*60*3.6319;
            pvEvents[x+4*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+3*pvPartNum].puGetTime());
        }
        for(int x = 0; x<pvPartNum; x++) {
            //rn220 to po216
            //type = alpha
            //energy = 6.404 MeV
            //halflife = 55.6 seconds
            String type = "alpha";
            double energy = 6.404;
            double halflife = 55.6;
            pvEvents[x+5*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+4*pvPartNum].puGetTime());
        }
        for(int x = 0; x<pvPartNum; x++) {
            //po216 to pb212
            //type = alpha
            //energy = 6.906 MeV
            //halflife = 0.145 seconds
            String type = "alpha";
            double energy = 6.906;
            double halflife = 0.145;
            pvEvents[x+6*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+5*pvPartNum].puGetTime());
        }
        for(int x = 0; x<pvPartNum; x++) {
            //pb212 to bi212
            //type = beta-
            //energy = 0.570
            //halflife = 10.64 hours
            String type = "beta-";
            double energy = 0.570;
            double halflife = 60*60*10.64;
            pvEvents[x+7*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+6*pvPartNum].puGetTime());
        }
        int numPO212 = Math.toIntExact(Math.round(Math.random()*pvPartNum)); 
        int numTI208 = pvPartNum - numPO212;
        //bi212 to either po212 or ti208
        //po212 type = beta-
        //ti208 type = alpha
        //po212 energy = 2.252 MeV
        //ti208 energy = 6.208 MeV
        //po212 halflife = 60.55 min
        //ti208 halflife = 60.55 min
        for(int x=0;x<numPO212;x++){
            String type = "beta-";
            double energy = 2.252;
            double halflife = 60*60.55;
            pvEvents[x+8*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+7*pvPartNum].puGetTime());
        }
        for(int x=0;x<numTI208;x++){
            String type = "alpha";
            double energy = 6.208;
            double halflife = 60*60.55;
            pvEvents[x+8*pvPartNum+numPO212] = new Event(halflife,energy,type,pvEvents[x+7*pvPartNum+numPO212].puGetTime());
        }
        
        for(int x = 0; x<numPO212; x++) {
            //po212 to pb208
            //type = alpha
            //energy = 8.955 MeV
            //halflife = 299 ns
            String type = "alpha";
            double energy = 8.955;
            double halflife = 299*Math.pow(10,-9);
            pvEvents[x+9*pvPartNum] = new Event(halflife,energy,type,pvEvents[x+8*pvPartNum].puGetTime());
        }
        for(int x = 0; x<numTI208; x++) {
            //po212 to pb208
            //type = beta-
            //energy = 4.999 MeV
            //halflife = 3.053 min
            String type = "beta-";
            double energy = 4.999;
            double halflife = 60*3.053;
            pvEvents[x+9*pvPartNum+numPO212] = new Event(halflife,energy,type,pvEvents[x+8*pvPartNum+numPO212].puGetTime());    
        }
    }
    public double[][] puGetEnergyAndTime() {
        double returned[][] = new double[pvPartNum*10][2];
        for (int x = 0;x<pvPartNum*10;x++) {
            returned[x][0]=pvEvents[x].puGetTime();
            returned[x][1]=pvEvents[x].puGetEnergy();
        }
        return returned;
    }

}

Finally is the Event.java class that actually generates when the random events occur based on half life.

 package Radioactivity;

public class Event {
    // An Event calculates and contains one radiative event 
    /* Variable and Function Nomenclature prescripts:
     * pv = private
     * pu = public
     * pvs = private static
     * pus = public static
     * pvsf = private static final
     * pusf = public static final
     */
    private double pvTime = 0.0; //calculated time of the event referenced from arbitrary start point in seconds 
    private double pvEnergy = 0.0; //user supplied event energy in MeV
    private String pvType; //user supplied event type (alpha, beta, gamma, neutron)
    private double pvHalfLife =0.0; //user supplied event half-life in seconds
    private int pvMaxHalfLives = 20;
    private double pvTimeOffset = 0.0; //user supplied offset time in seconds
    public Event(double halfLife, double energy, String type) {
        if (energy > 0) {
            pvEnergy = energy;
        } else {
            System.out.println("(Event) construction failed because (Event) input (energy) must be a positive number and greater than zero");
        }
        pvType = type;
        if (halfLife > 0) {
            pvHalfLife = halfLife;
        } else {
            System.out.println("(Event) construction failed because input (halflife) must be a positive number and greater than zero");
        }
        if (pvHalfLife > 0) {
            pvTime = pvCalcTime();
        } else {
            System.out.println("(Event) construction failed because (pvTime) cannot be calculated without a defined (halflife)");
        }
        pvMaxHalfLives = 20;
        pvTimeOffset = 0.0;
    }
    public Event(double halfLife, double energy, String type,double timeOffset) {
        if (timeOffset > 0) {
            pvTimeOffset = timeOffset;
        } else {
            System.out.println("(Event) construction failed because (timeOffset) input must be a positive number and greater than zero");
        }
        if (energy > 0) {
            pvEnergy = energy;
        } else {
            System.out.println("(Event) construction failed because (Event) input (energy) must be a positive number and greater than zero");
        }
        pvType = type;
        if (halfLife > 0) {
            pvHalfLife = halfLife;
        } else {
            System.out.println("(Event) construction failed because input (halflife) must be a positive number and greater than zero");
        }
        if (pvHalfLife > 0) {
            pvTime = pvCalcTime();
        } else {
            System.out.println("(Event) construction failed because (pvTime) cannot be calculated without a defined (halflife)");
        }
        pvMaxHalfLives = 20;
    }
    public Event(double halfLife, double energy, String type, int maxHalfLives) {
        if (energy > 0) {
            pvEnergy = energy;
        } else {
            System.out.println("(Event) construction failed because (Event) input (energy) must be a positive number and greater than zero");
        }
        pvType = type;
        if (halfLife > 0) {
            pvHalfLife = halfLife;
        } else {
            System.out.println("(Event) construction failed because input (halflife) must be a positive number and greater than zero");
        }
        if (maxHalfLives > 0) {
            pvMaxHalfLives = maxHalfLives;
        } else {
            System.out.println("Using default (pvMaxHalfLives) of 20 because the (maxHalfLives) supplied to the constructor was not a positive number and greater than zero");
            pvMaxHalfLives = 20;
        }
        if (pvHalfLife > 0) {
            pvTime = pvCalcTime();
        } else {
            System.out.println("(Event) construction failed because (pvTime) cannot be calculated without a defined (halflife)");
        }
        pvTimeOffset = 0.0;
        
    }
    public Event(double halfLife, double energy, String type,double timeOffset, int maxHalfLives) {
        if (timeOffset > 0) {
            pvTimeOffset = timeOffset;
        } else {
            System.out.println("(Event) construction failed because (timeOffset) input must be a positive number and greater than zero");
        }
        if (energy > 0) {
            pvEnergy = energy;
        } else {
            System.out.println("(Event) construction failed because (Event) input (energy) must be a positive number and greater than zero");
        }
        pvType = type;
        if (halfLife > 0) {
            pvHalfLife = halfLife;
        } else {
            System.out.println("(Event) construction failed because input (halflife) must be a positive number and greater than zero");
        }
        if (maxHalfLives > 0) {
            pvMaxHalfLives = maxHalfLives;
        } else {
            System.out.println("Using default (pvMaxHalfLives) of 20 because the (maxHalfLives) supplied to the constructor was not a positive number and greater than zero");
            pvMaxHalfLives = 20;
        }
        if (pvHalfLife > 0) {
            pvTime = pvCalcTime();
        } else {
            System.out.println("(Event) construction failed because (pvTime) cannot be calculated without a defined (halflife)");
        }

    }
    private double pvCalcTime() {
        double seed1 = Math.random();
        double seed2 = Math.random();
        double weightedLife = Math.pow(2,pvMaxHalfLives);
        double testWeightedLife = seed1 * weightedLife;
        double t = 0;
        int x = 0;
        while (t == 0) {
            if (x == (pvMaxHalfLives-1)) {
                t = (x+seed2) * pvHalfLife;
            } else if (testWeightedLife <= weightedLife*(1+(x*2))/Math.pow(2,x+1)){
                t = (x+seed2) * pvHalfLife;
            }
            x+=1;
        }    
        return (t+pvTimeOffset);
    }
    public double puGetTime() {
        if (pvTime > 0) {    
            return pvTime;
        } else {
            System.out.println("(puGetTime) failed because this (Event) does not have a calculated (pvTime)");
            return 0;
        }
    }
    public double puGetHalfLife() {
        if (pvHalfLife > 0) {    
            return pvHalfLife;
        } else {
            System.out.println("(puGetHalfLife) failed because this (Event) does not have a proper (pvHalflife) assigned");
            return 0;
        }
    }
    public String puGetType() {
        return pvType;
    }
    public double puGetEnergy() {
        if (pvEnergy > 0) {    
            return pvEnergy;
        } else {
            System.out.println("(puGetEnergy) failed because this (Event) does not have a proper (pvEnergy) assigned");
            return 0;
        }
    }
    public void puSetHalfLife(double halflife) {
        if (halflife > 0) {    
            pvHalfLife = halflife;
        } else {
            System.out.println("(puSetHalfLife) failed because the (halflife) provided is not greater than zero");
            pvHalfLife = 0;
        }
    }
    public void puSetHalfLife(double halflife, int maxhalflives) {
        if (halflife > 0) {    
            pvHalfLife = halflife;
            if (maxhalflives > 0) {
                pvMaxHalfLives = maxhalflives;
                pvTime = pvCalcTime();
            } else {
                System.out.println("(puSetHalfLife) failed because the (maxhalflives) provided is not greater than zero");
                pvMaxHalfLives = 0;
                pvTime = 0.0;
            }
        } else {
            System.out.println("(puSetHalfLife) failed because the (halflife) provided is not greater than zero");
            pvHalfLife = 0;
        }
    }
    public void puSetType(String newtype) {
        pvType = newtype;
    }
    public void puSetEnergy(double energy) {
        if (energy > 0) {    
            pvEnergy = energy;
        } else {
            System.out.println("(puSetEnergy) failed because the (energy) provided is not greater than zero");
            pvEnergy = 0;
        }
    }
}

QubesOS Security Tweak

The QubesOS R3 linux distro is a brilliantly smooth and fast sectionalized virtual machine-centric operating system. But it has some built-in customizations to it that are necessary to facilitate that speed and ease of use, but which require special attention when considering security. I’m referring to the QubesOS user management and sudoers. The system comes with numerous pre-defined users and all of these users are granted password free sudo access. This is fine as long as the user does not attempt to set the system up for some type of remote access under the assumption that new users will not have sudo access. The user could modify their firewall settings and install additional software that creates security vulnerabilities that they would not normally have suspected. To prevent this, I propose the following simple tweak to the net VM’s, dom0 and the template VM’s. The user account name is assumed to be Ivan in this example.

Open a terminal and edit the login access control table with:

sudo nano /etc/security/access.conf

Add the following lines at the bottom:

#Disallows console logins to all accounts except Ivan:
-:ALL EXCEPT Ivan:LOCAL 
#Disallows all non-local logins:
-:ALL:ALL EXCEPT LOCAL

Hit Ctrl-X and save the file. Next, open up the pam login configuration file to force the use of access.conf:

sudo nano /etc/pam.d/login

Add the following line at the bottom:

account    required     pam_access.so

Hit Ctrl-X and save the file. Repeat this process in all of the netVM’s, dom0, and the template VM’s.

It should now be impossible to log in to the system remotely.

Simple Relative Mental Functionality Logger (just a typing test)

The following code obtains and logs an error adjusted performance time for the copying of a simple random paragraph. This test measures the users speed and correctness in translating visual data into reasonably complex fine hand motions. It is intended to be used frequently in order for the user to establish a baseline and detect deviations therefrom. This data is subject to user bias, as the user would be able to arbitrarily lengthen their own times. Thus, the test doesn’t work if the user doesn’t put in their “best” effort, so to speak. The user must create two text files of their own as input and log files. The first test_words.txt should be populated with a list of line separated words that the user wishes to use in the randomly generated paragraphs. The second, test_scores.txt just needs to be created and left empty in the program directory prior to the first use.

It’s python (underscores must be replaced with spaces or tabs):

import sys
import random
from datetime import datetime, date, time, timedelta
try:
____f = open(‘test_words.txt’,’r’)
except:
____print “test_words.txt failed to open!”
words = []
for line in f:
____# print line
____words.append(line)
#print old
f.close()
test_set=random.sample(words,50)
test= “”
for word in test_set:
____word = word[0:len(word)-1]
____if test == “”:
________test=word
____else:
________test= test + ” ” + word
print “n”
print “n”
print test
print “n”
print “Please copy the above words exactly as they appear.”
print “n”
start_t = datetime.now()
user = raw_input()
end_t = datetime.now()
firsttime = end_t-start_t
firsterrors=0
index = 0
for index in range(0,len(test)):
____try:
________if test[index] == user[index]:
____________continue
________else:
____________firsterrors+=1
________if isinstance(user[index],string):
____________continue
________else:
____________firsterrors+=1
____except:
________firsterrors+=1
print “n”
print “errors: ” + str(firsterrors)
print “time: ” + str(firsttime.total_seconds())
print “error adjusted time: ” + str(firsttime.total_seconds()+5*firsterrors)
print “n”
try:
____f=open(“/media/usbdisc/test_scores.txt”,”r”)
except:
____print “Failed to open test_scores.txt”
scores=[]
for line in f:
____scores.append(line[0:len(line)-1])
f.close()
scores.append(str(end_t)+” “+”errors= ” +str(firsterrors)+ ” test time= “+str(firsttime.total_seconds())+” error adjusted time: ” + str(firsttime.total_seconds()+5*firsterrors))
write_scores = “”
for score in scores:
____write_scores = write_scores + str(score) + “n”
try:
____f2=open(“test_scores.txt”,”w+”)
except:
____print “Failed to open test_scores.txt”
try:
____f2.truncate()
____f2.write(write_scores)
____f2.close()
except:
____f2.close()
____print “Failed to Write Scores!”