#!/usr/bin/perl



# speedvolt program to compute particle speed from volts or vice versa
# going to attempt to add createguilocal to this for gtk3 data after __DATA__

use Modern::Perl '2015'; # perl 5.20 
use File::Basename 'dirname'; # for knowing where we are (ease for developer)
use Gtk3 -init; # for our GUI
#use Glib  qw(TRUE FALSE); # for periodic events etc
#use Gtk3::Helper; # allows us to add "watch" callbacks to handles?
#http://askubuntu.com/questions/319568/i-cant-configure-rhythmbox-as-gobject-introspection-1-is-not-installed for when you can't install gtk3 or glib
#use Storable qw(nstore retrieve); # for (re) storing hash of hashes preset

# "constants"
my $statvolt = 299.792458; # volts/statvolt
my $pracunit = 5.97e7; # but will correct this
my $c = 299792458; # m/ss
my $Em2e = 9.10938356e-28 / 1.59e-20;  #4.80326e-10; # stat units, electron mass/charge

# modern units
my $Ce = 1.60217662e-19; # coloumbs charge
my $Me = 9.10938356e-31; # mass in kg
#my $eCM = $Ce/$Me; # electron charge/mass
my $eMC = $Me/$Ce; # mass/charge

# N/C is volts/meter fwiw

# https://www.youtube.com/watch?v=gSIF6CU_0-E is the math for coloumbs, neutons, meters, kg (not funky units)
# http://www.dummies.com/education/science/physics/how-to-calculate-acceleration/
# 
# F = V/D * charge in above units, D in meters, result in newtons
# A = F/Me = newtons/kg (meters/sec**2)  Me for electron in kG, Me times weight ratio for others
# A = 2D/t**2 (D in meters, t in seconds)

# Vf**2 = 2AD (D in meters) - there is a direct in eV somewhere else?
# Vf = sqrt (2AD)  assuming zero initial speed
# also Vf = 5.97e7 sqrt(volts * mass/Me); (terman)
# T = Vf/A
# 
# given time to distance, what was volts per distance?  Total volts.

my $debug; # set to be verbose at terminal

#############################
my $mainwin;
my $builder = Gtk3::Builder->new(); # gtkbuilder object, creates a gui from glade's xml
my %mcratios = (electron=>1,proton=>1822.888486192,deuteron=>3670.48296783,triton=>5496.92153712,He31=>5496.88511216,He32=>2748.44255608);
my ($speedtxtr,$speedtxt);
my ($volttxtr,$volttxt);
my ($manualmer,$manualme);
my ($particler,$particle);
my ($microsecondsr,$microseconds);
my ($CMr,$CM);
my ($VCMr,$VCM);
my ($totalvr,$totalv);

####################################################################
sub createguifile # create the gui from xml in a .glade file 
{ # use this for developer convienience.  Final product should put glade xml
  # after the __END__ tag and use createguilocal instead
 $builder->add_from_file(dirname($0) . '/speedvolt.glade'); #@@@ hardcoded filename
 $mainwin = $builder->get_object('mainwin'); #@@@ assumes main window is called mainwin
 $builder->connect_signals(undef);
 $mainwin->set_screen( $mainwin->get_screen() ); #??? from an example.  Seems redundant?
 $mainwin->signal_connect(destroy => sub {Gtk3->main_quit});
 $mainwin->show_all();
# not so program-specific you couldn't use it again
}
####################################################################
sub createguilocal # create the gui from xml in a .glade file 
{ # put glade xml after the __END__ tag and use createguilocal
 my $guidata; # packed the xml internally, goes here
 local $/; # which makes this undefined for this sub
 $guidata = <main::DATA>; # which makes this slurp the entire "file"
 $builder = Gtk3::Builder->new_from_string($guidata,length($guidata));
 $mainwin = $builder->get_object('mainwin'); #@@@ assumes main window is called mainwin
 $builder->connect_signals(undef);
 $mainwin->set_screen( $mainwin->get_screen() ); #??? from an example.  Seems redundant?
 $mainwin->signal_connect(destroy => sub {Gtk3->main_quit});
 $mainwin->show_all();
}
####################################################################
sub on_particle_changed {
 $manualme = $mcratios{$particler->get_active_text()}; # jam this from hash selection
 $manualmer->set_text($manualme);
}
####################################################################
sub on_speedtxt_changed {
 $speedtxt = $speedtxtr->get_text();
 if ($speedtxt =~ m/[-+]?[0-9]*\.?[0-9]+/)
 {
 $speedtxt =~ s/[A-Za-z,\[\]\{\(\^\$\*\?;'\/]//g; #@@@ this could be lots better, for example get rid of odd punctuation, second .
 $speedtxtr->set_text($speedtxt);
 say "speedtxt changed:$speedtxt" if $debug;
 } else {say "not a number, my fixups failed";}
}
# this one looks interesting: ^-?\\d*(\\.\\d+)?$
####################################################################
sub on_volttxt_changed {
 $volttxt = $volttxtr->get_text();
 if ($volttxt =~ m/[-+]?[0-9]*\.?[0-9]+/)
 {
 $volttxt =~ s/[A-Za-z,\[\]\{\(\^\$\*\?;'\/]//g; #@@@ this could be lots better, for example get rid of odd punctuation, second .
 $volttxtr->set_text($volttxt);
 say "volttxt changed:$volttxt" if $debug;
 } else {say "not a number, my fixups failed";}
}
####################################################################
sub on_speed_clicked {
# say "speed kills";
 $speedtxt = $pracunit * sqrt($volttxt/($manualme));
 $speedtxtr->set_text($speedtxt);
}
####################################################################
sub on_volts_clicked {
# say "I'm shocked";
 $volttxt = $manualme * ($speedtxt/$pracunit)**2;
 $volttxtr->set_text($volttxt);
}
####################################################################
sub on_compgrad_clicked {
	#VCMr VCM
 say "statv:$statvolt, Em2e:$Em2e,manme:$manualme, uS:$microseconds" if $debug;
# $VCM = $statvolt * 2 * $Em2e * $manualme * $CM / ($microseconds / 1000000)**2;
 
 my $accel = 2*($CM/100) / ($microseconds/1000000)**2; # meters/sec/sec
 say "Accel = $accel M/s/s" if $debug;
 
 $VCM = $accel * $eMC * $manualme; # volts per meter here
 $VCM *= 100/$CM;
 $totalv = $VCM * $CM;
 $VCMr->set_text($VCM);
 $totalvr->set_text($totalv);	

}
####################################################################
sub on_microseconds_changed {
 $microseconds = $microsecondsr->get_text();
 if ($microseconds =~ m/[-+]?[0-9]*\.?[0-9]+/)
 {
 $microseconds =~ s/[A-Za-z,\[\]\{\(\^\$\*\?;'\/]//g; #@@@ this could be lots better, for example get rid of odd punctuation, second .
 $microsecondsr->set_text($microseconds);
 say "microseconds changed:$microseconds" if $debug;
 } else {say "not a number, my fixups failed";}

}
####################################################################
sub on_CM_changed {
 $CM = $CMr->get_text();
 if ($CM =~ m/[-+]?[0-9]*\.?[0-9]+/)
 {
 $CM =~ s/[A-Za-z,\[\]\{\(\^\$\*\?;'\/]//g; #@@@ this could be lots better, for example get rid of odd punctuation, second .
 $CMr->set_text($CM);
 say "centimeters changed:$CM" if $debug;
 } else {say "not a number, my fixups failed";}

}
####################################################################

####################################################################

sub getwidgetrefs{
 $speedtxtr = $builder->get_object('speedtxt');
 $volttxtr = $builder->get_object('volttxt');
 $manualmer = $builder->get_object('manualme');
 $particler = $builder->get_object('particle');
 $microsecondsr = $builder->get_object('microseconds');
 $CMr = $builder->get_object('CM');
 $VCMr = $builder->get_object('VCM');
 $totalvr = $builder->get_object('totalv');
}
####################################################################

sub init {
# createguifile;
 createguilocal;
 getwidgetrefs;
 on_particle_changed; # to get initial values into manual edit box variable
 on_CM_changed; # simulate a typing event
 on_microseconds_changed;
 Gtk3->main; # GUI event loop - when we quit, we fall out and exit
 say "I'm done";
}
#########################################################################################
################################ MAIN  ##################################################
#########################################################################################

init;

#gtk3 gui xml goes after end
__END__
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
  <requires lib="gtk+" version="3.10"/>
  <object class="GtkApplicationWindow" id="mainwin">
    <property name="can_focus">False</property>
    <property name="tooltip_text" translatable="yes">Compute speed from eV or vice versa</property>
    <property name="title" translatable="yes">SpeedVolt</property>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkGrid" id="grid1">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkButton" id="speed">
                <property name="label" translatable="yes">Speed Cm/S</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_speed_clicked" after="yes" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="volts">
                <property name="label" translatable="yes">Electron volts</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="xalign">0.51999998092651367</property>
                <property name="yalign">0.52999997138977051</property>
                <signal name="clicked" handler="on_volts_clicked" after="yes" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">3</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label1">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Speed:</property>
                <property name="ellipsize">end</property>
                <property name="lines">0</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="speedtxt">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="text" translatable="yes">0</property>
                <property name="shadow_type">out</property>
                <property name="primary_icon_tooltip_text" translatable="yes">Speed in centimeters per second</property>
                <property name="input_purpose">number</property>
                <signal name="changed" handler="on_speedtxt_changed" after="yes" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label2">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Cm/S	Volts:</property>
              </object>
              <packing>
                <property name="left_attach">2</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="volttxt">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="tooltip_text" translatable="yes">Energy in electron-volts</property>
                <property name="text" translatable="yes">0</property>
                <property name="input_purpose">number</property>
                <signal name="changed" handler="on_volttxt_changed" after="yes" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">3</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label3">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">eV</property>
              </object>
              <packing>
                <property name="left_attach">4</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label4">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">particle</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label5">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">ion	manual:</property>
              </object>
              <packing>
                <property name="left_attach">2</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="manualme">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="input_purpose">number</property>
              </object>
              <packing>
                <property name="left_attach">3</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label6">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">electron masses/e</property>
              </object>
              <packing>
                <property name="left_attach">4</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label7">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Compute:</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label8">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Compute:</property>
              </object>
              <packing>
                <property name="left_attach">2</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkComboBoxText" id="particle">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="active">0</property>
                <property name="active_id">0</property>
                <items>
                  <item translatable="yes">electron</item>
                  <item translatable="yes">proton</item>
                  <item translatable="yes">deuteron</item>
                  <item translatable="yes">triton</item>
                  <item translatable="yes">He31</item>
                  <item translatable="yes">He32</item>
                </items>
                <signal name="changed" handler="on_particle_changed" after="yes" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkGrid" id="grid2">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <child>
              <object class="GtkLabel" id="label11">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">microseconds</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label12">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">centimeters</property>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label13">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">volts/cm</property>
              </object>
              <packing>
                <property name="left_attach">2</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="microseconds">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="text" translatable="yes">5</property>
                <property name="input_purpose">number</property>
                <signal name="changed" handler="on_microseconds_changed" after="yes" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="CM">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="text" translatable="yes">10</property>
                <signal name="changed" handler="on_CM_changed" after="yes" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">1</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="VCM">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="editable">False</property>
              </object>
              <packing>
                <property name="left_attach">2</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label10">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">particle above</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label9">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">gradient computation</property>
              </object>
              <packing>
                <property name="left_attach">4</property>
                <property name="top_attach">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label14">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">command</property>
              </object>
              <packing>
                <property name="left_attach">4</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton" id="compgrad">
                <property name="label" translatable="yes">Compute Gradient</property>
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <signal name="clicked" handler="on_compgrad_clicked" after="yes" swapped="no"/>
              </object>
              <packing>
                <property name="left_attach">4</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkLabel" id="label15">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">total V</property>
              </object>
              <packing>
                <property name="left_attach">3</property>
                <property name="top_attach">1</property>
              </packing>
            </child>
            <child>
              <object class="GtkEntry" id="totalv">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="editable">False</property>
              </object>
              <packing>
                <property name="left_attach">3</property>
                <property name="top_attach">2</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">1</property>
          </packing>
        </child>
        <child>
          <placeholder/>
        </child>
      </object>
    </child>
  </object>
</interface>
