Created
December 26, 2024 18:48
-
-
Save thomasjslone/146ee1b0551a978ca5431f9649a5df58 to your computer and use it in GitHub Desktop.
minor bug fixes to controller and install process
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## installer version 1.4 | |
## no package included, paste one into the last line of the file, you can generate one using install.build_package | |
## RubinSystem is a ruby app runtime environment. Multi-Instance, bot controller on Mingw Windows Ruby | |
## ## !! WARNING !! If you did not download this script from github or the official website, DO NOT RUN IT! | |
## Run this script to install Rubin System in either the current directory or one you enter. | |
## | |
#begin | |
$version='1.0.13';launch_directory=Dir.getwd; launch_time=Time.now | |
##prompt | |
puts "Welcome to the Rubin System installer. Version "+$version.to_s | |
puts "" | |
puts "Dir: "+launch_directory.to_s | |
puts "" | |
puts "Would you like to install to this location? (Y/N)" | |
inp=gets.chomp.to_s[0].downcase | |
if inp=="y"; install_dir=Dir.getwd.to_s | |
else | |
puts "Enter install directory." | |
install_dir=nil | |
loop { inp=gets.chomp.to_s; if File.directory?(inp.to_s); install_dir=inp.to_s; break;elsif inp.to_s.downcase == "exit"; exit; else; puts "Invalid directory."; end } | |
end | |
puts "Confirming, you want to install to dir? (Y/N) ; "+install_dir.to_s | |
inp=gets.chomp.to_s[0].downcase | |
if inp!="y"; puts "Fine, then stop wasting my time...\nThe program will exist in 3 seconds."; sleep 3.0; exit; end | |
if File.directory?(install_dir+"/Rubin"); puts "Cannot install here, there is already an installation."; sleep 3.0; exit; end | |
#load data | |
dir=install_dir | |
if File.file?($0); p = $0 | |
elsif File.file?(launch_directory+"/rubin_installer.rb"); p=launch_directory+"/rubin_installer.rb" | |
else; raise "The installer file cannot locate its self: "+$0.to_s | |
end | |
f=File.open(p,"r"); data = f.read ; f.close | |
#split up package data | |
data=data.split(";;;"+";;").join("\n") | |
maindatasep="#1#::#1"+"#::#0#::#0#::#0#"+"::#1#::#1#" | |
filenamesep="#1#::#1#::"+"#0#::#0#::#0#"+"::#0#::#1#" | |
filesep="#1#::#1#::#0#::#0"+"#::#0#"+"::#0#::#0#" | |
index_sep="#1#::#0#:"+":#0#::#0#::#0#"+"::#0#::#1#" | |
data=data.split(maindatasep)[-1] | |
index_string=data.to_s.split(index_sep)[0].to_s | |
file_data=data.split(index_sep)[-1] | |
##process files | |
file_data=file_data.split(filesep); nfile_data=[] | |
file_data.each { |d| p=d.split(filenamesep)[0]; di=d.split(filenamesep)[1]; nfile_data<<[p,di] } | |
file_data=nfile_data | |
#proces index | |
f = index_string.split("??")[0].split("?") | |
di = index_string.split("??")[1].split("?") | |
#build dirs | |
Dir.mkdir(dir.to_s+"/rubin") | |
di.each { |p| np=dir+"/"+p; Dir.mkdir(np) } | |
# write files | |
file_data.each { |fd| p=dir.to_s+"/"+fd[0].to_s; f=File.open(p,"w"); f.write(fd[1].to_s); f.close } | |
## write installation_header | |
p=dir.to_s+"/rubin/system/rubin.rb" | |
f=File.open(p,"r"); dat=f.read; f.close | |
old_header=dat.split("\n")[0].split("INSTALLATION_HEADER=")[-1] | |
old_header=eval(old_header.to_s) | |
dat=dat.split("\n")[1..-1].join("\n") | |
version=old_header[2].to_s | |
head=["installed",(dir+"/rubin").split("//").join("/"),version,Time.now.to_s,ENV["USER"].to_s,rand(99999999999999).to_s(36)] | |
str="INSTALLATION_HEADER="+head.to_s | |
ndat=str+"\n"+dat | |
f=File.open(p,"w"); f.write(ndat); f.close | |
## | |
puts "INSTALL SUCCESS!!!" | |
puts "The program will exit in 2 seconds" | |
sleep 2.0 | |
exit | |
## INSTALL PACKAGE BELOW | |
#1#::#1#::#0#::#0#::#0#::#1#::#1#/rubin/system/rubin.rb?/rubin/system/daemond.rb?/rubin/system/definitions.rb?/rubin/launch.rb?/rubin/doc.txt?/rubin/launch irb.cmd?/rubin/launch rubin.cmd?/rubin/data/scripts/systemlogmonitor.rb?/rubin/data/scripts/logmonitor.rb?/rubin/data/scripts/unpackaged_installer_script.rb?/rubin/data/scripts/install_builder.rb?/rubin/data/scripts/file_backup.rb?/rubin/app/app_template.rb?/rubin/system/component.rb??/rubin/system?/rubin/bin?/rubin/app?/rubin/class?/rubin/data?/rubin/shortcuts?/rubin/data/appdata?/rubin/data/backups?/rubin/data/config?/rubin/data/definitions?/rubin/data/fileio?/rubin/data/logs?/rubin/data/scripts?/rubin/data/components?/rubin/data/sys?/rubin/data/sys/instance?/rubin/data/temp?/rubin/data/user#1#::#0#::#0#::#0#::#0#::#0#::#1#/rubin/system/rubin.rb#1#::#1#::#0#::#0#::#0#::#0#::#1#INSTALLATION_HEADER=["installed", "C:/Users/home-server/Documents/Rubin", "1.0.13", "2024-06-22 16:30:53 -0700", "home-server", "5txovpumj"];;;;;##INSTALLATION_HEADER above;;;;;;;;;;BOOT_INIT_TIME = Time.now.to_s ; MAIN = self ; INSTANCE = rand(100000) ; RUBIN_CORE_FILE = __FILE__;;;;;boot_log = [BOOT_INIT_TIME + " : BOOT STARTING."];;;;;if ARGV[1].to_s.downcase == "true" ; $debug = true ; else ; $debug = false ; end;;;;;;;;;;##verify read permission;;;;;unless File.readable?(Dir.getwd);;;;; boot_log << "BOOT ERROR : Homedir read permission not granted by file system: "+Dir.getwd;;;;; raise boot_log[-1];;;;;end;;;;;;;;;;##check for debug flag;;;;;if File.file?(Dir.getwd+"/debug.flag") == true or File.file?(Dir.getwd+"/data/config/debug.flag") ; $debug = true ; end;;;;;;;;;;##verify write access;;;;;unless File.writable?(Dir.getwd);;;;; boot_log << "BOOT ERROR : Homedir write permission not granted by file system: "+Dir.getwd;;;;; raise boot_log.join("\n");;;;;end;;;;;;;;;;## verify system core file (this file);;;;;unless File.file?(__FILE__);;;;; boot_log << "BOOT ERROR : System core file could not be located: "+__FILE__.to_s + " Workdir: " + Dir.getwd;;;;; raise boot_log.join("\n");;;;;end;;;;;;;;;;##verify system core file read access;;;;;unless File.readable?(__FILE__);;;;; boot_log << "BOOT ERROR : System core file does not provide read permission: " + __FILE__.to_s;;;;; raise boot_log.join("\n");;;;;end;;;;;;;;;;##verify system core file write access;;;;;unless File.writable?(__FILE__);;;;; boot_log << "BOOT ERROR : System core file does not provide write permission: " + __FILE__.to_s;;;;; raise boot_log.join("\n");;;;;end;;;;;;;;;;#check /system;;;;;unless File.directory?(Dir.getwd+"/system");;;;; boot_log << "The /system dir could not be located, please reinstall rubin.";;;;; rasie boot_log.join("\n");;;;;end;;;;;;;;;;##verify /system read permission;;;;;unless File.readable?(Dir.getwd+"/system");;;;; boot_log << "BOOT ERROR : Sysdir read permission not granted by file system: "+Dir.getwd+"/system";;;;; raise boot_log[-1];;;;;end;;;;;;;;;;##verify /system write access;;;;;unless File.writable?(Dir.getwd+"/system");;;;; boot_log << "BOOT ERROR : Sysdir write permission not granted by file system: "+Dir.getwd+"/system";;;;; raise boot_log.join("\n");;;;;end;;;;;;;;;;#check system core file is able to be located;;;;;unless Dir.getwd.to_s.downcase+"/system/rubin.rb" != __FILE__;;;;; boot_log << "BOOT ERROR: The system core file is not in the location it is expected to be. __FILE__: "+__FILE__.to_s + " ; Expected location: " + Dir.getwd+"/system/rubin.rb";;;;; raise boot_log.join("\n");;;;;end;;;;;;;;;;## verify HOST_OS;;;;;if ENV["OS"].downcase=="windows_nt" and File.directory?("C:/Windows");;;;; HOST_OS="Windows_NT";;;;; boot_log << "Windows_NT operating system detected.";;;;; if File.writable?("C:/") ; boot_log << "Full file system access.";;;;; else ; boot_log << "Limited file system access.";;;;; end;;;;; system("TITLE RubinSystem"+INSTALLATION_HEADER[2].to_s+" Instance: "+INSTANCE.to_s + " @ " + ENV["USERNAME"].to_s+" ; PID "+$$.to_s+" Dir: "+INSTALLATION_HEADER[1].to_s);;;;;elsif File.directory?("/home");;;;; HOST_OS = "linux";;;;; boot_log << "Linux operating system detected, cannot boot because linux support has not yet been added.";;;;; raise boot_log.join("\n");;;;;else;;;;; HOST_OS="unknown";;;;; boot_log << "Unknown host system.";;;;; puts "UNKNOWN HOST SYSTEM, LAUNCH ANYWAYS? (Y/N)";;;;; #if gets.chomp.downcase[0] != "y" ; raise boot_log.join("\n") ; end ## enable this line and disable the line below to run on unknown hosts;;;;; raise boot_log.join("\n");;;;;end ;;;;;;;;;;##check installation header and install location, update header if install was moved;;;;;if Dir.getwd.to_s.downcase != INSTALLATION_HEADER[1].to_s.downcase ;;;;; boot_log << "Installation was recently moved. Install dir: "+INSTALLATION_HEADER[1].to_s + " Workdir: "+Dir.getwd.to_s ;;;;; begin;;;;; new_homedir = Dir.getwd;;;;; path=new_homedir+"/system/rubin.rb";;;;; data=File.read(path);;;;; header=data.split("\n")[0];;;;; header=header.split("=")[-1];;;;; header = self.instance_eval(header);;;;; header[1]=new_homedir;;;;; INSTALLATION_HEADER=header;;;;; header="INSTALLATION_HEADER="+header.to_s;;;;; ndata=header.to_s+"\n"+data.split("\n")[1..-1].join("\n");;;;; f=File.open(path,"w"); f.write(ndata); f.close;;;;; $homedir=Dir.getwd;;;;; boot_log << "Installation header install path was updated.";;;;; rescue;;;;; boot_log << "Failed to update installation header install location.";;;;; end;;;;; if $debug ; puts boot_log[-1] ; end;;;;;else ##installation is where we expected it to be;;;;; $homedir = Dir.getwd;;;;; boot_log << "Installation verified.";;;;; if $debug ; puts boot_log[-1] ; end;;;;;end;;;;;;;;;;## verify daemond exists;;;;;unless File.file?(Dir.getwd+"/system/daemond.rb");;;;; f=File.open(Dir.getwd+"/system/daemond.rb","w") ; f.close;;;;; boot_log << "Daemond file was not present, created an empty one as a placeholder.";;;;; if $debug ; puts boot_log[-1] ; end;;;;;end;;;;;;;;;;## verify ruby version;;;;;if RUBY_VERSION.split(".").join("").to_i < 150;;;;; boot_log << "Ruby version is too outdated to boot. Ruby Version: "+RUBY_VERSION.to_s;;;;; raise boot_log.join("\n");;;;;else;;;;; boot_log << "Ruby_Version: "+RUBY_VERSION.to_s;;;;;end;;;;;;;;;;##check host ruby;;;;;if HOST_OS == "Windows_NT";;;;; path = `PATH`;;;;; rpath = false;;;;; path.split("\\").join("/").downcase.split(";").each do |p|;;;;; if p.split("/")[1][0..3] == "ruby";;;;; rpath = p;;;;; boot_log << "Host ruby located: "+p.to_s;;;;; HOST_RUBY_PATH = rpath;;;;; break;;;;; end;;;;; end;;;;; if rpath == false;;;;; boot_log << "Unable to locate host ruby.";;;;; HOST_RUBY_PATH = "";;;;; else;;;;; if File.file?(HOST_RUBY_PATH+"/ruby.exe");;;;; if File.size?(HOST_RUBY_PATH+"/ruby.exe");;;;; boot_log << "Host ruby verified.";;;;; HOST_RUBY_INTERPRETER = HOST_RUBY_PATH + "/bin/ruby.exe";;;;; else;;;;; boot_log << "Host ruby could not be verified.";;;;; HOST_RUBY_INTERPRETER = "";;;;; end;;;;; else;;;;; boot_log << "Host ruby could not be verified.";;;;; end;;;;; end;;;;;elsif HOST_OS == "linux";;;;; boot_log << "Host ruby cannot be verified on linux yet.";;;;;else ##unknown host os;;;;; boot_log << "Host ruby cannot be verified on unknown host.";;;;;end;;;;;;;;;;## create global links to COREDIRS from hidden internal data;;;;;hdat = File.read(RUBIN_CORE_FILE).split("#H#;#I#;#D"+"#;"+"#D#;#E#;#N#;#I#;#"+"N#;#T#;#E#;"+"#R#;#N#;#W#;#O#;#R#"+";#D#;#A#;#S#;#S#;#H#\n##")[-1].split("\n")[1][2..-1];;;;;links = [];;;;;begin;;;;; coredirs = self.instance_eval(hdat);;;;; coredirs.each do |d|;;;;; begin;;;;; self.instance_eval(d[0] + "=$homedir+'"+d[1]+"'");;;;; links << d[0];;;;; rescue;;;;; boot_log << "ERROR: Failed to create COREDIR link: "+d[0] + "=$homedir+'"+d[1]+"'";;;;; end;;;;; end;;;;; rescue;;;;; boot_log << "ERROR: Unable to parse COREDIRS from Hidden_Internal_Data";;;;; raise boot_log.join("\n");;;;; end;;;;;links.insert(0,"$homedir");;;;;COREDIRS = links;;;;;;;;;;## BOOT CHECK OK;;;;;BOOT_TIME=Time.now ;;;;;boot_log << Time.now.to_s+" : BOOT SUCCESS";;;;;;;;;;##store this boots data in home so system can grab it once startup has begun;;;;;f=File.open($homedir+"/bootlog.log","a");f.write(boot_log.join("\n")+"\n");f.close;;;;;if $debug == true ; s = " (DEBUG MODE)" ; else ; s = "" ; end;;;;;if $debug; puts "Loading RubinSystem... Version "+INSTALLATION_HEADER[2].to_s + s.to_s; end;;;;;;;;;;#################################################################################################;;;;;;;;;;class RubinSystem;;;;; ;;;;; VERSION=INSTALLATION_HEADER[2].to_s ## LAST VERSION UPGRADE 2024.12.6;;;;; ;;;;; def initialize;;;;; ## create system instance variables;;;;; @homedir=$homedir;;;;; @app=nil;@threads=[] ## reserved for system to launch apps ;;;;; @shutdown = false;;;;; @shell=nil ## systemshell is the components classname, fix later;;;;; @daemond=nil ## reserved for main system threadpool;;;;; @definitions=[];;;;; @apps=[] ## list of app objs and threads loaded # we might move this into Rubin::Apps (app controller);;;;; @cache = [];;;;; @daemond = nil ; @controller = nil; @instance = nil; @install = nil; @host = nil; @ruby = nil; @network = nil ;;;;; @components=[];;;;; @sysdir_components = [];;;;; @loaded_config = [];;;;; @loaded_scripts = [];;;;; @loaded_files = [] ## list of every file loaded since runtime.;;;;; @loaded_apps = [] ## list of app loads on system ##revise these too THIS IS SHIT CODE RIGHT HERE;;;;; @loaded_classes = [] ##### @classes is the name of the variable we actually use;;;;; @loaded_definitions = [];;;;; @loaded_apps = [];;;;; @required_files = [];;;;; @config_overide = false ;;;;; end;;;;; ;;;;; def post_initialize *args ## create system objects;;;;; if defined?(@POST_INITIALIZATION); return "false"; end;;;;; ;;;;; ##create instance variable links to coredirs;;;;; if COREDIRS.length == 0 ; SYSTEM.errorlog("Rubin.startup: COREDIRS could not be processed, this error should never occur.");;;;; else;;;;; COREDIRS.each do |c|;;;;; begin ; SYSTEM.instance_eval("@" + c[1..-1] + " = " + c) ;;;;; rescue ; SYSTEM.errorlog("Rubin.startup: Failed to process COREDIR: " + c.to_s + " into instance variables for system class. Startup will fail!");;;;; end;;;;; end;;;;; end;;;;; ## create method links to coredirs;;;;; if COREDIRS.length > 0;;;;; COREDIRS.each do |c|;;;;; SYSTEM.instance_eval("def homedir ; return @homedir ; end");;;;; begin ; SYSTEM.instance_eval("def " + c[1..-1] + " ; return @"+c[1..-1] + "; end");;;;; rescue ; SYSTEM.errorlog("Rubin.startup: Failed to create method link to coredir: " + c.to_s + ".");;;;; end;;;;; end;;;;; end;;;;;;;;;; ## move bootllog from homedir into major boot log;;;;; begin;;;;; if File.file?(@homedir+"/bootlog.log");;;;; log = File.read(@homedir + "/bootlog.log");;;;; f = File.open(@homedir+"/bootlog.log","a") ; f.write(log) ; f.close;;;;; File.delete(@homedir+"/bootlog.log");;;;; else ; SYSTEM.errorlog("Rubin.startup: Boot log for current boot is missing!");;;;; end;;;;; rescue ; SYSTEM.errorlog("Rubin.startup: Failed to move over boot log.");;;;; end;;;;;;;;;; self.writelog("Rubin.startup: ##### SYSTEM STARTUP IS INITIALIZING ###############################################.");;;;; ;;;;; ## check filesystem for startup, repaire any missing coredirs;;;;; begin;;;;; dat = File.read(RUBIN_CORE_FILE).split("#H#;#I#;#D"+"#;"+"#D#;#E#;#N#;#I#;#"+"N#;#T#;#E#;"+"#R#;#N#;#W#;#O#;#R#"+";#D#;#A#;#S#;#S#;#H#\n##")[-1].split("\n")[0];;;;; dat = eval(dat) ; dat=dat[0];;;;; dat.each do |f|;;;;; unless File.directory?(@homedir+f);;;;; begin ;;;;; Dir.mkdir(@homedir+f);;;;; self.errorlog("SYSTEM ERROR: Missing directory repaired: "+@homedir+f.to_s);;;;; rescue ;;;;; end;;;;; end;;;;; end;;;;; rescue;self.errorlog("Rubin.startup: Unable to verify FSYS.");;;;; end;;;;;;;;;; ## setup config data;;;;; @config_names=["LoadClasses","AutoStartApps","Required",;;;;; "SystemShellAutoStart","DebugMode","DaemondDelay","ShowLogWrites",;;;;; "CtrlNetdir","LoadDefinition","EvaluateFileIO","EvaluateFileIOPrint",;;;;; "RubyGems","AutoScripts","ShellSessions","LoadSysdirComponents",;;;;; "StartupShutdownScripts","SystemDaemondFile"];;;;; ;;;;; @config_descriptions=["",;;;;; "",;;;;; "",;;;;; "",;;;;; "",;;;;; ""];;;;; ;;;;; @default_config=[true,[],["bundler/inline", "open-uri", "net/http", "fileutils", "win32ole", "fiddle/import","win32/api"],true,true,10,false,"",true,false,false,[],[],true,true,[true,true],true];;;;; @config=@default_config;;;;; @loaded_config="";;;;; ;;;;; ;;;;; ## load config;;;;; SYSTEM.writelog "Rubin.startup: Looking for config...";;;;; if ARGV[2].to_s.length > 0 and ARGV[2].to_s.downcase != "false" ; if File.file?(@cfgdir+"/"+ARGV[2].to_s) ; @config_overide = ARGV[2] ; end ; end ;;;;; if @config_overide != false;;;;; self.writelog("Rubin.startup: Overide config found: "+@config_overide.to_s);;;;; self.load_config(@config_overide);;;;; elsif @config_overide == false and File.file?(@cfgdir + "/altconfig.cfg");;;;; begin ; path = File.read(@cfgdir+"/altconfig.cfg");;;;; if File.file?(path) ; SYSTEM.load_config(path);;;;; else;;;;; raise "";;;;; end;;;;; rescue;;;;; SYSTEM.errorlog("Rubin.startup: Failed to locate alt config.");;;;; SYSTEM.load_config;;;;; end;;;;; else;;;;; preconfigs = [];;;;; Dir.entries(@cfgdir).each do |d| ; d = d.to_s.downcase;;;;; if d == "." or d == ".." ; next ; end;;;;; if d[0..8] == "preconfig" and d[-4..-1] == ".cfg" ; preconfigs << d ; end;;;;; end;;;;; preconfigs = preconfigs.sort;;;;; if preconfigs.length > 0;;;;; SYSTEM.load_config(preconfigs[0]);;;;; begin ; File.delete(@cfgdir+"/"+preconfigs[0]);;;;; rescue;;;;; SYSTEM.errorlog("Rubin.startup: Failed to remove preconfig: "+preconfigs[0].to_s);;;;; SYSTEM.load_config ;;;;; end;;;;; else;;;;; SYSTEM.load_config;;;;; end;;;;; end;;;;;;;;;; ## load SYSTEM CACHE;;;;; if File.file?(@datadir+"/cache.dat"); self.load_cache;;;;; else;# self.save_cache ##cache isnt always used;;;;; end;;;;;;;;;; ##require files;;;;; if @config[2] == [] or @config[2].to_s == "";;;;; ##no required files;;;;; elsif @config[2].is_a?(Array);;;;; begin ; s = @config[2].to_a.length.to_s ; rescue ; s = "0" ; end;;;;; SYSTEM.writelog("Rubin.startup: " + s + "required files will be loaded ");;;;; @config[2].each do |f|;;;;; begin;;;;; require f.to_s ; @loaded_files<<f ; @required_files << f;;;;; SYSTEM.writelog("Rubin.startup: Required file: "+f.to_s);;;;; rescue => e;;;;; SYSTEM.errorlog("Rubin.startup: Failed to require file: " + f.to_s + "\nError: "+ e.to_s+"\n"+e.backtrace.join("\n")+"\n");;;;; end;;;;; end;;;;; if $debug ; if s.to_i != @loaded_files.length ; SYSTEM.errorlog("Rubin.startup: Failed to require some files: Actually loaded: "+ @loaded_files.length.to_s + "/" + s.to_s) ; end ; end;;;;; else ## INVALID VALUE;;;;; @config[2] = [];;;;; SYSTEM.save_config(@loaded_config) ;;;;; SYSTEM.errorlog("Rubin.startup: Config 2 RequiredFiles contained invalid data, it was reset. ");;;;; end;;;;;;;;;; ##load/install rubygems;;;;; if @config[11].is_a?(Array);;;;; if @config[11].length > 0;;;;; if $debug; puts "Loading Ruby Gems..."; end;;;;; required=@config[11];;;;; gems=`gem list`;gems=gems.split("\n");;;;; gemfiles=[];gems.each {|g| gemfiles<<g.split(" (")[0]};;;;; required.each do |r|;;;;; v = require r.to_s;;;;; if gemfiles.include?(r)==false and v != true;;;;; self.writelog("Rubin.startup: Attempting to install rubygem: "+r) ;;;;; if $debug; puts "Ruby gem is being installed: "+r+" ..."; end;;;;; begin;;;;; gemfile do;;;;; source 'https://rubygems.org';;;;; if r.to_s == "win32/api" ; r = "win32-api" ; end ##this is why we stick to naming conventions, REMOVE THIS LINE IF THEY EVER DECIDE TO FIX THE NAME;;;;; gem r.to_s;;;;; end;;;;; require r.to_s ;;;;;; @loaded_gems << r;;;;; rescue;;;;; SYSTEM.errorlog("Rubin.startup: Ruby gem could not be installed: "+r.to_s);;;;; end;;;;; else;require r.to_s ; @loaded_files << r;;;;; end;;;;; end;;;;; end;;;;; elsif @config[11] == false;;;;; ##no rubygems;;;;; else ## INVALID VALUE;;;;; SYSTEM.errorlog("Rubin.startup: Config 11 RubyGems contained an invalid value. It was reset.");;;;; @config[11]=[];;;;; self.save_config(@loaded_config);;;;; end ;;;;; ;;;;; ;;;;; ## load definitions ;;;;; if @config[8] == [] or @config[8].to_s.downcase == "false" or @config[8].to_s == "";;;;; ##no definitions;;;;; elsif @config[8].to_s.downcase == "true" or @config[8].is_a?(Array);;;;; definitions = [];;;;; if @config[8].is_a?(Array) ; definitions = @config[8] ; else ; definitions << "definitions.rb" ; end ;;;;; definitions.each do |d|;;;;; begin;;;;; begin ; f = File.open(@sysdir + "/" + d.to_s,"r") ; script = f.read ; f.close;;;;; rescue ; raise "Failed to read file.";;;;; end;;;;; MAIN.instance_eval(script) ; @loaded_files<<"definitions.rb" ; @loaded_definitions << "definitions.rb";;;;; SYSTEM.writelog("Rubin.startup: Applied definition: " + d.to_s);;;;; rescue => e;;;;; SYSTEM.errorlog("Rubin.startup: Definition: " + d.to_s + " produced an excption.\n"+e.to_s+"\n"+e.backtrace.join("\n"));;;;; end;;;;; end;;;;; if $debug ; puts "Loaded definitions: " + @loaded_definitions.to_s ; end;;;;; else ## INVALID VALUE;;;;; self.errorlog("Rubin.startup: Config 8 LoadDefinition contained an invalid value, it was reset.");;;;; @config[8]=true;;;;; self.save_config(@loaded_config);;;;; end;;;;; ;;;;; ## Load classes;;;;; if @config[0].to_s == "" or @config[0] == [];;;;; ## no classes;;;;; elsif @config[0].to_s.downcase == "true";;;;; SYSTEM.load_classdir;;;;; elsif @config[0].is_a?(Array);;;;; SYSTEM.load_classdir(@config[0]);;;;; else ## INVALID VALUE;;;;; SYSTEM.errorlog "Rubin.startup: Config 0 LoadCladdDir contained an invalid value, it was reset.";;;;; @config[8] = true;;;;; self.save_config(@loaded_config);;;;; end;;;;; ;;;;; ## load embedded components;;;;; @embedded_components = [];;;;; @embedded_component_objects = [];;;;; ## IF YOU MAKE CHANGES TO EMBEDDED COMPONENTS YOU MUST UPDATE THIS LIST;;;;; [:@daemond, :@app_controller, :@shell, :@instance, :@host, :@install, :@controller, :@network,:@ruby].each { |c| @embedded_components << c };;;;; ;;;;; @daemond=SystemDaemond.new ;;;;; @app_controller = Apps.new #;;;;; @shell=SystemShell.new ;;;;; @instance = Instance.new #;;;;; @host = Host_Manager.new # ;;;;; @install = Installation_Manager.new # ;;;;; @controller = Controller.new ;;;;; @network = Network_Manager.new() # ;;;;; @ruby = Ruby_Manager.new() # ;;;;; SYSTEM.writelog("Rubin.startup: "+@embedded_components.length.to_s+" embedded system components were initialized. "+@embedded_components.to_s);;;;; ;;;;; ec=[@daemond,@app_controller,@shell,@instance,@host,@install,@controller,@network,@ruby];;;;; ec.each { |c| @embedded_component_objects << c };;;;; ;;;;; ## load sysdir components if configed;;;;; @sysdir_components=[];;;;; @component_objects=[];;;;; @components=[];;;;; preivs=self.instance_variables ;;;;; if @config[14]==true;;;;; ;;;;; c=Dir.entries(@sysdir); c.delete("."); c.delete("..");;;;; c.each {|c| unless c.to_s.downcase=="rubin.rb" or c.to_s.downcase=="daemond.rb" or c.to_s.downcase[0..9]=="definition" and c.to_s.downcase[-3..-1] == ".rb" ; @components<<c.to_s; @sysdir_components<<c.to_s;end};;;;; if @components.length>0;;;;; SYSTEM.writelog("Rubin.startup: Loading system component files: "[email protected]_s);;;;; @components.each do |c|;;;;; begin;;;;; load @sysdir+"/"+c; @loaded_files << c.to_s;;;;; begin;;;;; SYSTEM.instance_eval("@" + (c.to_s.downcase.split(".rb")[0].to_s) + "=" + (c.to_s.downcase.split(".rb")[0].to_s).capitalize + ".new");;;;; v = "@" + (c.to_s.downcase.split(".rb")[0].to_s);;;;; rescue => e;;;;; self.errorlog("Rubin.startup: SYSDIR component could not be created: " + e.to_s + "\n" + e.backtrace.join("\n"));;;;; end;;;;; rescue => e ;if $debug; puts e.to_s; end;;;;; self.errorlog("Rubin.startup: System component load resulted in excpetion: "+c.to_s+" "+e.to_s+" "+e.backtrace.join("\n"));;;;; end;;;;; end ;;;;; end;;;;; ;;;;; ##isolate newly created component instance variables;;;;; postivs=self.instance_variables ; preivs.each { |iv| postivs.delete(iv) } ;;;;; @components=postivs;;;;; @components.each do |c| ; self.instance_eval("@component_objects << "+c.to_s) ; end;;;;; ;;;;; if postivs.length>0; SYSTEM.writelog("Rubin.startup: Initialized "+postivs.length.to_s+" components. "[email protected]_s) ; end;;;;; loaded_comp = [];;;;; ##create sysdir component method links;;;;; if @sysdir_components.length > 0;;;;; @sysdir_components.each do |c|;;;;; c = c.to_s.downcase.split(".rb")[0];;;;; begin;;;;; if (eval("defined?(@"+c+")")).to_s == "instance-variable";;;;; begin ; SYSTEM.instance_eval("def " + c.to_s + " ; return @" + c.to_s + " ; end") ; loaded_comp << c.to_s ; SYSTEM.writelog("Rubin.startup: SYSDIR component loaded: " + c.to_s);;;;; rescue ; SYSTEM.errorlog("Rubin.startup: Failed to create method link to component: " + c.to_s);;;;; end;;;;; else;;;;; SYSTEM.errorlog("Rubin.startup: Cannot find component: " + c.to_s + ", it may not have been properly loaded.");;;;; next;;;;; end;;;;; rescue ; SYSTEM.errorlog("Rubin.startup: Failed to process sysdir component name: " + c.to_s);;;;; end;;;;; end;;;;; if loaded_comp.length > 0 ; if $debug ; puts "Loaded SYSDIR components: "+loaded_comp.to_s ; end ; end;;;;; end;;;;; ;;;;; end;;;;; ;;;;; ## FINAL STARTUP CHECKS;;;;; ;;;;; self.writelog("Rubin.startup: RubinSystem initialization completed.");;;;; return 0 ;;;;; end;;;;; ##end of startup method;;;;; ;;;;; ;;;;; def startup;;;;; unless defined?(@POST_INITIALIZATION) == "instance-variable" ;;;;; @POST_INITIALIZATION = true;;;;; @startup_time = Time.now;;;;; ;;;;; ##post_init embedded components;;;;; if @embedded_components.length > 0;;;;; ic=[];;;;; @embedded_component_objects.each do |c|;;;;; if c.methods.include?(:post_initialize);;;;; c.post_initialize;;;;; ic << c.class.to_s;;;;; end;;;;; @components << ("@"+c.class.to_s.downcase.to_s.split("rubinsystem::")[-1]).to_sym ## no need for these really;;;;; end;;;;; SYSTEM.writelog("Rubin.startup: "+ic.length.to_s+" embedded system components were post initialized: "+ic.to_s);;;;; end;;;;; ##post_init other components;;;;; if @component_objects.length > 0;;;;; @component_objects.each do |c|;;;;; if c.methods.include?(:post_initialize);;;;; c.post_initialize;;;;; self.writelog("Rubin.post_initialize: System component post initialized: "+c.to_s);;;;; end;;;;; end;;;;; end;;;;; ;;;;; ## run startup script;;;;; startup_scripts = [];;;;; if @config[15][0].to_s.downcase == "false" or @config[15][0] == [] or @config[15][0].to_s == "";;;;; ## no startup scripts;;;;; elsif @config[15][0].to_s == "true";;;;; if File.file?(@datadir + "/scripts/startup.rb") ; startup_scripts << "startup.rb" ; end;;;;; elsif @config[15][0].to_s == "TRUE";;;;; Dir.entries(@datadir + "/scripts").each do |d|;;;;; if d.to_s == "." or d.to_s == ".." or File.file?(@datadir + "/scripts/" + d.to_s) == false or d.to_s.downcase[-3..-1] != ".rb" or d.to_s.downcase[0..6] != "startup" ; next;;;;; else ; startup_scripts << d;;;;; end;;;;; end;;;;; elsif @config[15][0].is_a?(Array);;;;; @config[15][0].each do |f| ; if File.file?(@datadir + "/scripts/" + f.to_s) ; startup_scripts << f.to_s ; end ; end;;;;; else ## INVALID VALUE;;;;; @config[15][0] = [];;;;; SYSTEM.save_config;;;;; SYSTEM.errorlog("Rubin.post_initialize: Config 15,0 StartupShutdownScripts had an invalid value, it had to be reset.");;;;; end;;;;; if startup_scripts.length > 0;;;;; SYSTEM.writelog("Rubin.post_initialize: Found "+startup_scripts.length.to_s + " startup scripts.");;;;; startup_scripts.each do |s| ; SYSTEM.runs(s.to_s) ; end;;;;; end ;;;;; ;;;;; ## run startup apps;;;;; if @config[1] == [] or @config[1].to_s == "" or @config[1].to_s.downcase == "false";;;;; ## no autostart apps;;;;; else;;;;; if @config[1].is_a?(Array);;;;; SYSTEM.writelog("Loading "+@config[1].length.to_s+" startup apps.");;;;; @config[1].each do |app| ; SYSTEM.run(app) ; end ;;;;; else ## INVALID VALUE;;;;; @config[1] = [];;;;; SYSTEM.save_config;;;;; SYSTEM.errorlog("Rubin.post_initialize: Config 1 AutostartApps had an invalid value, it had to be reset.");;;;; end;;;;; end;;;;; ## run apps autostart behavior;;;;; if @apps.length > 0;;;;; @apps.each do |a|;;;;; if a[3] == nil ; next ; end;;;;; if a[3].methods.include?(:autostart_behavior);;;;; begin ; a[3].autostart_behavior;;;;; rescue; SYSTEM.errorlog("Rubin.post_initialize: " + a[0].to_s + "App autostart_behavior produced an exception: " + e.to_s + "\n" + e.backtrace.join("\n"));;;;; end;;;;; end;;;;; end;;;;; end;;;;; ;;;;; ## STARTUP COMPLETE;;;;; self.writelog("Rubin.post_initialize: System startup successfull.");;;;; if $debug; ;;;;; puts "Startup complete. Instance: "+self.instance.id.to_s+" "+self.to_s;;;;; #puts "Started up in "+(Time.now-BOOT_INIT_TIME).to_s[0..3]+" seconds. "+Time.now.to_s.split(" ")[0..1].join(" ")+", Loaded " + @loaded_files.length.to_s+" files.";;;;; end;;;;; ;;;;; ## run auto scripts;;;;; if @config[12].to_s == "" or @config[12] == [] or @config[12].to_s.downcase == false;;;;; ## no auto scripts;;;;; elsif @config[12].is_a?(Array);;;;; autoscripts = [];;;;; @config[12].each do |s|;;;;; if File.file?(@datadir + "/scripts/" + s.to_s) ; autoscripts << s.to_s;;;;; else ; SYSTEM.errorlog("Rubin.post_initialize: Autoscript listed in config[12] does not exist: " + s.to_s);;;;; end;;;;; end;;;;; if autoscripts.length > 0;;;;; autoscripts.each do |s| ; SYSTEM.runs(s) ; end;;;;; end;;;;; else ## INVALID VALUE;;;;; @config[12] = [];;;;; self.save_config(@loaded_config);;;;; SYSTEM.errorlog("Rubin.startup: Config[12] contains invalid data:" +@config[12].to_s[0..20]+". It had to be reset.") ;;;;; end;;;;; ;;;;; ## run shell;;;;; if @config[3].to_s.downcase=="true";;;;; self.writelog("Rubin.post_initialize: Starting system shell.");;;;; if $no_shell != true;;;;; if $debug; puts "Starting system shell."; end;;;;; self.shell.start(self);;;;; else ; SYSTEM.writelog("$no_shell is set, skipped shell.");;;;; end;;;;; end;;;;; ;;;;; end;;;;; end;;;;; ## end of startup method;;;;; ########################;;;;;;;;;; def cls; SYSTEM.shell.cls; end;;;;; def get_config;return @config;end;;;;; def loaded_components;return @components; end;;;;; def loaded_files; return @loaded_files; end;;;;; ;;;;;;;;;; ## create method links to embedded system components, we might stream line this upto where embedded components are created above;;;;; begin;;;;; def shell ; return @shell ; end;;;;; def install ; return @install ; end;;;;; def daemond ; return @daemond ; end;;;;; def ruby ; return @ruby ; end;;;;; def network ; return @network ; end;;;;; def host ; return @host ; end;;;;; def instance ; return @instance ; end;;;;; def controller ; return @controller ; end;;;;; def apps; return @app_controller ; end;;;;; alias :con :controller;;;;; alias :net :network;;;;; rescue; self.errorlog("Rubin was unable to define method links to all loaded components.");;;;; end;;;;;;;;;;;;;;; def show_config;;;;; str=""; cfg=[]; i=0; @config_names.each { |n| cfg << i.to_s+" "+n.to_s+"= "+@config[i].to_s; i += 1 };;;;; str << "Rubin system config: "+@loaded_config.to_s+"\n\n"; str << cfg.join("\n").to_s+"\n"; return str;;;;; end ;;;;; alias :config? :show_config;;;;;;;;;; def dir *args;;;;; if args.length == 0 ; return MAIN.dir;;;;; else ; return MAIN.dir(args[0].to_s);;;;; end;;;;; end;;;;; ;;;;; def dirs *args;;;;; if args.length == 0 ; dirs = [] ; COREDIRS.each { |d| dirs << d[1..-1] } ; return dirs ; end;;;;; if COREDIRS.include?("$"+args[0].to_s.downcase);;;;; begin ; return eval("@"+args[0].to_s.downcase);;;;; rescue ; raise "An error occured while looking up COREDIR: "+args[0].to_s + ", you may consider renaming it to avoid this error.";;;;; end;;;;; else ; return false;;;;; end;;;;; end;;;;; ;;;;; def apps? *args;;;;; if args.length > 0;;;;; check = [];;;;; if args[0].is_a?(String) or args[0].is_a?(Symbol) ; check = [args[0].to_s];;;;; elsif args[0].is_a?(Array) ; if args[0].length == 0 ; return nil ; else ; args[0].each do |a| ; check << a.to_s ; end ; end;;;;; else ; raise "Invalid arguments for Rubin.apps?";;;;; end;;;;; apps = [];;;;; Dir.entries(@appdir).each do |f|;;;;; if f.to_s == "." or f.to_s == ".." ; next ; end;;;;; if f.to_s.downcase[-3..-1] == ".rb" and File.file?(@appdir + "/" + f.to_s) ; apps << f.downcase;;;;; elsif File.directory?(@appdir +"/" + f) and File.file?(@appdir + "/" + f + "/" + f + ".rb") ; apps << f.downcase + ".rb";;;;; end;;;;; end;;;;; found = true;;;;; check.each do |a|;;;;; if a.to_s.downcase[-3..-1] != ".rb" ; a = a + ".rb" ; end;;;;; if apps.include?(a.downcase) == false ; found = false ; break ; end;;;;; end;;;;; return found;;;;; else;;;;; apps = [];;;;; Dir.entries(@appdir).each do |f|;;;;; if f.to_s == "." or f.to_s == ".." ; next ; end;;;;; if f.to_s.downcase[-3..-1] == ".rb" and File.file?(@appdir + "/" + f.to_s) ; apps << f.downcase;;;;; elsif File.directory?(@appdir +"/" + f) and File.file?(@appdir + "/" + f + "/" + f + ".rb") ; apps << f.downcase + ".rb";;;;; end;;;;; end;;;;; return apps ;;;;; end;;;;; end;;;;;;;;;; def scripts? *args;;;;; if args.length == 1;;;;; if args[0].to_s.downcase[-3..-1] != ".rb" ; a = args[0].to_s + ".rb" ; else ; a = args[0].to_s ; end;;;;; return File.file?(@datadir + "/scripts/" + a);;;;; elsif args.length == 0;;;;; a = [];;;;; Dir.entries(@datadir+"/scripts").each do |f|;;;;; if f.to_s == "." or f.to_s == ".." ; next ; end;;;;; if File.file?(@datadir+"/scripts/"+f.to_s) ; if f.to_s.downcase[-3..-1] == ".rb" ; a << f ; end ; end;;;;; end;;;;; return a;;;;; else ; raise "Invalid arguements for Rubin.scripts?";;;;; end;;;;; end;;;;;;;;;; def logs? *args;;;;; if args.length == 1;;;;; if args[0].to_s.downcase[-4..-1] != ".log" ; a = args[0].to_s + ".log" ; else ; a = args[0].to_s ; end;;;;; return File.file?(@logdir + "/" + a);;;;; elsif args.length == 0;;;;; a = [];;;;; Dir.entries(@logdir).each do |f|;;;;; if f.to_s == "." or f.to_s == ".." ; next ; end;;;;; if File.file?(@logdir+"/"+f.to_s) ; if f.to_s.downcase[-4..-1] == ".log" ; a << f ; end ; end;;;;; end;;;;; return a;;;;; else ; raise "Invalid arguements for Rubin.logs?";;;;; end;;;;; end;;;;;;;;;; def config_files? *args;;;;; if args.length == 1;;;;; if args[0].to_s.downcase[-4..-1] != ".cfg" ; a = args[0].to_s + ".cfg" ; else ; a = args[0].to_s ; end;;;;; return File.file?(@cfgdir + "/" + a);;;;; elsif args.length == 0;;;;; a = [];;;;; Dir.entries(@cfgdir).each do |f|;;;;; if f.to_s == "." or f.to_s == ".." ; next ; end;;;;; if File.file?(@cfgdir+"/"+f.to_s) ; if f.to_s.downcase[-4..-1] == ".cfg" ; a << f ; end ; end;;;;; end;;;;; return a;;;;; else ; raise "Invalid arguements for Rubin.config_files?";;;;; end;;;;; end;;;;;;;;;; def altconfig?;;;;; if File.file?(@cfgdir+"/altconfig.cfg") == false ; return false ; end;;;;; begin ; if File.file?(@cfgdir + "/" + (File.read(@cfgdir+"/altconfig.cfg"))) ; return f ; else ; return false ; end;;;;; rescue;;;;; SYSTEM.errorlog("Rubin.altconfig?: Failed to read altconfig pointer file.");;;;; raise "Failed to read altconfig pointer file.";;;;; end;;;;; end;;;;;;;;;; def preconfig?;;;;; found = [];;;;; Dir.entries(@cfgdir).each do |f| ; if f.to_s.downcase[0..8] == "preconfig" and File.file?(@cfgdir+"/"+f) ; found << f ; end ; end;;;;; return found.sort;;;;; end;;;;; ;;;;; def writelog *args# ad option to print;;;;; if File.file?(@logdir+"/systemlog.log")==false;f=File.open(@logdir+"/systemlog.log","w");f.close;end;;;;; ts=Time.now.to_s.split(" ")[0..1].join(".").split(":").join(".").split("-").join(".");;;;; str="\n"+ts+": "+INSTANCE.to_s+": "+args[0].to_s;;;;; f=File.open(@logdir+"/systemlog.log","a");f.write(str);f.close;;;;; begin;;;;; if args[1].to_s.downcase=="true" and @config[6].to_s != "true"; puts "\n"+args[0].to_;;;;; elsif SYSTEM.config("ShowLogWrites") == true;;;;; puts args[0].to_s;;;;; end;;;;; rescue;;;;; end;;;;; end;;;;;;;;;; def errorlog(msg) ;;;;; ts=Time.now.to_s.split(" ")[0..1].join(".").split(":").join(".").split("-").join(".");;;;; str="\n"+ts+": "+INSTANCE.to_s+": "+msg.to_s;;;;; str2="\n"+ts+": "+INSTANCE.to_s+": An error occured: "+msg.to_s;;;;; f=File.open(@logdir+"/errorlog.log","a");f.write(str.to_s);f.close ;;;;; if SYSTEM.config("DebugMode") == true;;;;; f=File.open(@logdir+"/systemlog.log","a");f.write(str2.to_s);f.close ;;;;; puts "ERROR: " + msg.to_s;;;;; end;;;;; end ;;;;;;;;;; def read_log *args;;;;; if args[0].to_s == ""; raise "Input requires logpath."; end; path = args[0];;;;; if File.file?(SYSTEM.logdir+"/"+path) == false and File.file?(SYSTEM.logdir+"/"+path+".log"); path = SYSTEM.logdir+"/"+path+".log";;;;; elsif File.file?(SYSTEM.logdir+"/"+path); path = SYSTEM.logdir+"/"+path;;;;; end;;;;; if args[1].is_a?(Integer); index = args[1].to_i;;;;; elsif args[1].is_a?(Range); index = args[1];;;;; else; index = true;;;;; end;;;;; if File.file?(path);;;;; f = File.open(path,"r"); dat = f.read; f.close;;;;; ndat = dat.split("\n");;;;; if index == true; return ndat;;;;; else; return ndat[index];;;;; end;;;;; else; return "No such file: "+args[0].to_s;;;;; end;;;;; end ;;;;;;;;;; def clean_logs;;;;; files = []; cleaned = [];;;;; cont=Dir.entries(SYSTEM.logdir); cont.delete("."); cont.delete("..");;;;; if cont.length == 0 ; return nil;;;;; else; cont.each { |c| if c.downcase.end_with?(".log") or c.downcase.end_with?(".txt"); if File.size?(SYSTEM.logdir+"/"+c)>0; files << c; end; end};;;;; end;;;;; if files.length == 0 ; return "There were no logs to clean"; end;;;;; files.each do |f|;;;;; p = SYSTEM.logdir+"/"+f;;;;; begin;;;;; f=File.open(p,"r"); dat=f.read;f.close;;;;; if dat.split("\n").length > 1000;;;;; SYSTEM.writelog "Cleaning log file: "+p.split("/")[-1];;;;; ndat = [];;;;; d=dat.split("\n")[-999..-1];;;;; File.delete(p);;;;; f=File.open(p,"w"); f.write(ndat); f.close;;;;; SYSTEM.writelog "Cleaned log: "+p.split("/")[-1];;;;; cleaned << p.split("/")[-1];;;;; end;;;;; rescue; SYSTEM.errorlog "Log cleaning was unable to open file: "+f.to_s;;;;; end;;;;; end;;;;; SYSTEM.writelog "Log cleaner cleaned "+cleaned.length.to_s+" logs. "+cleaned.to_s;;;;; if cleaned.length == 0 ; return "No logs were cleaned.";;;;; else; return cleaned.length.to_s+" logs were cleaned. ("+cleaned.to_s+")";;;;; end;;;;; end;;;;; ;;;;; def measure_logs;;;;; files = []; ret = [];;;;; cont=Dir.entries(SYSTEM.logdir); cont.delete("."); cont.delete("..");;;;; if cont.length == 0 ; return nil;;;;; else; cont.each { |c| if c.downcase.end_with?(".log") or c.downcase.end_with?(".txt"); files << c; end};;;;; end;;;;; if files.length == 0 ; return [];;;;; else##;;;;; files.each do |f|;;;;; file=File.open(SYSTEM.logdir+"/"+f.to_s,"r"); dat=file.read.to_s; file.close;;;;; lines=dat.split("\n").length;;;;; ret << [f.to_s,"Lines: "+lines.to_s,"Size: "+File.size?(SYSTEM.logdir+"/"+f.to_s).to_s];;;;; end;;;;; return ret;;;;; end;;;;; end;;;;; ;;;;; def empty_log(path);;;;; if path.to_s == ""; raise "Input requires logpath."; end;;;;; path = args[0];;;;; if File.file?(SYSTEM.logdir+"/"+path) == false and File.file?(SYSTEM.logdir+"/"+path+".log");;;;; path = SYSTEM.logdir+"/"+path+".log";;;;; puts "Fixed path: "+ path.to_s;;;;; elsif File.file?(SYSTEM.logdir+"/"+path);;;;; path = SYSTEM.logdir+"/"+path;;;;; else; raise "Unable to locate log.";;;;; end;;;;; f = File.open(path,"w"); f.write(Time.now.to_s+" Log was emptied.");f.close;;;;; return true;;;;; end;;;;;;;;;; ## SHUTDOWN / RESTART METHODS ;;;;; def shutdown_sequence *args ## user and app requests go through here, use arg true to skip countdown;;;;; if @shutdown != false; return false; end ; @shutdown = true;;;;; SYSTEM.writelog("Rubin.shutdown_sequence: System shutdown process has begun.");;;;;;;;;; shutdownscript=false;;;;; if @config[15][1] == true; shutdownscript = true ; end;;;;; if shutdownscript == true and File.file?($datadir+"/scripts/shutdown.rb");;;;; begin; SYSTEM.instance_eval(File.read($datadir+"/scripts/shutdown.rb"));;;;; rescue => e ; SYSTEM.errorlog("Rubin.shutdown_sequence: Shutdown script produced and exception: "+e.to_s+"\n"+e.backtrace.join("\n"));;;;; end;;;;; end;;;;; #countdown thread;;;;; unless args[0] == true ; Thread.new {@shutdown = 30; 30.times{ sleep 1.0; begin; @shutdown -= 1 ;rescue;;end }; } ; end;;;;; self.save_config;;;;; self.save_cache;;;;; if @apps.length > 0;;;;; @apps.each { |a| ;;;;; if a[3] == nil ; next ; end;;;;; if a[3].methods.include?(:shutdown_behavior);;;;; begin ; a[3].shutdown_behavior;;;;; rescue => e ; SYSTEM.errorlog("Rubin.shutdown_sequence: " + a[0] + " shutdown_behavior produced an exception: " + e.to_s + "\n" + e.backtrace.join("\n"));;;;; end;;;;; end;;;;; } ;;;;; SYSTEM.writelog("Rubin.shutdown_squence: Stopped apps.");;;;; end;;;;; if SYSTEM.daemond!= nil;;;;; SYSTEM.daemond.shutdown;;;;; SYSTEM.writelog("Rubin.shutdown_sequence: Stopped daemond.");;;;; end ;;;;; begin; File.delete(@datadir+"/sys/instance/"+INSTANCE.to_s+".dat"); rescue; end;;;;; SYSTEM.writelog("Rubin.shutdown_sequence: System is down.");;;;; ##wait for countdown then call exit;;;;; if args[0] != true ; Thread.new {loop do ; sleep 1.0 ; if @shutdown < 1 ; exit ; end ; end };;;;; else ; exit;;;;; end;;;;; return true;;;;; end;;;;; ;;;;; def shutdown *args ## system requests go through here, this links to sequence however args[0] bypass prompt ; args[1] bypass countdown;;;;; if @shutdown != false; return false; end;;;;; proceed=false;;;;; if args[0] == true; proceed=true;;;;; else; puts "\nAre you sure you want to shutdown Rubin? Y/N";;;;; inp=gets.chomp[0].downcase;;;;; if inp=="y";proceed=true;end;;;;; end;;;;; if proceed;;;;; if args[0] == true;;;;; SYSTEM.writelog("Rubin.shutdown: System Shutdown F");;;;; SYSTEM.shutdown_sequence(args[1]);;;;; else;;;;; SYSTEM.writelog("Rubin.shutdown: System shutdown sequence has been requested.");;;;; SYSTEM.shutdown_sequence(args[1]);;;;; end;;;;; return true;;;;; else;;;;; return false;;;;; end;;;;; end;;;;; ;;;;; def restart *args;;;;; proceed=false;;;;; if args[0] == true; proceed=true;;;;; else; puts "\nAre you sure you want to restart Rubin? (Y/N)";;;;; inp=gets.chomp[0].downcase;;;;; if inp=="y";proceed=true;end;;;;; end;;;;; if proceed==false; return false; end;;;;; SYSTEM.writelog("Rubin.restart: Preparing to restart Rubin, System shutdown process has begun. ");;;;; SYSTEM.host.launch_new(@homedir+"/launch.rb");;;;; SYSTEM.shutdown_sequence(true);;;;; return true;;;;; end;;;;; ;;;;; def hard_restart *args;;;;; proceed=false;;;;; if args[0].to_s[0]=="F"; proceed=true;;;;; else; puts "\nAre you sure you want to HARD RESTART Rubin? You may lose data. (Y/N)";;;;; inp=gets.chomp[0].downcase;;;;; if inp=="y";proceed=true;end;;;;; end;;;;; if proceed==false; return false; end;;;;; begin;File.delete(@datadir+"/sys/instance/"+INSTANCE.to_s+".dat"); rescue;; end;;;;; SYSTEM.writelog("Rubin.hard_restart: HARD RESTART, about to restart.");;;;; if args[0].to_s!="F"; sleep 1.0;end;;;;; SYSTEM.host.launch_new(@homedir+"/launch.rb");;;;; if args[0].to_s!="F"; sleep 0.1; end;;;;; exit;;;;; end;;;;; ;;;;; def hard_shutdown *args;;;;; proceed=false;;;;; if args[0] == true ; proceed=true;;;;; else; puts "\nAre you sure you want to HARD SHUTDOWN Rubin? You may lose data. (Y/N)";;;;; inp=gets.chomp[0].downcase;;;;; if inp=="y";proceed=true;end;;;;; end;;;;; if proceed;;;;; begin; File.delete(@datadir+"/sys/instance/"+INSTANCE.to_s+".dat"); rescue;; end;;;;; SYSTEM.writelog("Rubin.hard_shutdown: HARD SHUTDOWN, about to shutdown.");;;;; exit;;;;; end;;;;; end;;;;; ;;;;; ## CONFIG METHODS;;;;; def config *args;;;;; old_config=eval(@config.to_s) ##....just...WHY?! maybe to catch corruptions?;;;;; ;;;;; if args.length==0 ## RETURN;;;;; cfg=[];@config_names.each {|c| cfg << [c,@config[@config_names.index(c)]]};;;;; return cfg;;;;; elsif args[0].is_a?(Integer) and args.length==1 ## RETURN [Int];;;;; return @config[args[0].to_i];;;;; elsif args[0].is_a?(Integer) and args.length==2 ## SET [Int]=;;;;; @config[args[0]]=args[1];;;;; elsif args[0].is_a?(String) or args[0].is_a?(Symbol) and @config_names.include?(args[0].to_s) and args.length==1 ## RETURN [Str];;;;; return @config[@config_names.index(args[0].to_s)];;;;; elsif args[0].is_a?(String) or args[0].is_a?(Symbol) and @config_names.include?(args[0].to_s) and args.length==2 ##;;;;; @config[@config_names.index(args[0].to_s)]=args[1];;;;; else;raise "Invalid argument.";;;;; end;;;;; ;;;;; ## detect changes and perform auto response to config changes;;;;; ci = []; i = 0;;;;; old_config.each { |oc| if oc.to_s != @config[i].to_s; ci << i; end; i+=1 };;;;; if ci.include?(0) ; ; end;;;;; if ci.include?(1) ; ; end;;;;; if ci.include?(2) ; ; end;;;;; if ci.include?(3) ; ; end;;;;; if ci.include?(4) ## config 4 debug;;;;; if @config[4] == true; $debug = true; else; $debug = false; end;;;;; if @config[4] == true and File.file?(@cfgdir+"/debug.flag") == false; f=File.open(@cfgdir+"/debug.flag","w");f.close; end;;;;; if @config[4] != true and File.file?(@cfgdir+"/debug.flag") == true; File.delete(@cfgdir+"/debug.flag"); end;;;;; if @config[4] != true and File.file?(@homedir+"/debug.flag") == true; File.delete(@homedir+"/debug.flag"); end ## because boot also checks here;;;;; puts "DEBUG flag was changed: "+$debug.to_s;;;;; end;;;;; return true;;;;; end;;;;; ;;;;; def load_config *args ## you can pass a filepath to load config from or leave blank to load default;;;;; file=false;;;;; if args.length==0 and File.file?(@cfgdir+"/config.cfg");;;;; file=@cfgdir+"/config.cfg";;;;; elsif File.file?(@cfgdir+"/"+args[0].to_s) and args[0].to_s[-4..-1].to_s.downcase==".cfg";;;;; file=@cfgdir+"/"+args[0].to_s;;;;; else;;;;; return false;;;;; end;;;;; f=File.open(file.to_s,"r");cfg=f.read;f.close;;;;; begin;cfg=eval(cfg);@config=cfg;@loaded_config=file.to_s;SYSTEM.writelog("Loaded config: "+file.to_s);;;;; if @config[4] == false and File.file?(@cfgdir+"/debug.flag") == true;;;;; @config[4] = true;;;;; elsif @config[4] == true and $debug != true;;;;; $debug = true;;;;; end;;;;; if $debug ; puts "Config loaded: "+file.to_s.split("/")[-1] ; end;;;;; return true;;;;; rescue ## CONFIG DATA CORRUPTED ;;;;; self.errorlog("System config load failed due to corruption.");;;;; return false ;;;;; end ;;;;; end;;;;; ;;;;; def save_config *args ## you can pass a name to save config as or blank for default;;;;; if args.length==0;;;;; f=File.open(@cfgdir+"/config.cfg","w");f.write(@config.to_s);f.close;;;;; self.writelog("System config saved.");;;;; elsif args[0].to_s.length>0;;;;; if args[0].is_a?(String);;;;; begin;;;;; f=File.open(@cfgdir+"/"+args[0].to_s+".cfg","w");f.write(@config.to_s);f.close;;;;; self.writelog("System config saved as '"+args[0].to_s+"'.cfg.");;;;; ##continue;;;;; rescue;;;;; return false;;;;; end;;;;; elsif args[0].is_a?(Array);;;;; begin;;;;; f=File.open(@cfgdir+"/"+args[1].to_s,"w"); f.write(args[0].to_s);;;;; ##continue;;;;; rescue;;;;; return false;;;;; end;;;;; else; raise "Invalid arguments.";;;;; end;;;;; else;;;;; return false;;;;; end;;;;; ##can reach here unless falses above are avoided;;;;; if @config[4] == true and File.file?(@cfgdir+"/debug.flag") == false;;;;; $debug = true;;;;; f = File.open(@cfgdir+"/debug.flag","w") ; f.close;;;;; elsif @config[4] == false and File.file?(@cfgdir+"/debug.flag") == true;;;;; begin ; File.delete(@cfgdir+"/debug.flag") ; $debug = false ; end;;;;; end;;;;; return true;;;;; end;;;;; ;;;;; def repair_config;;;;; self.writelog("System Config data is being repaired.");;;;; begin;;;;; f=File.open(SYSTEM.cfgdir+"/config.cfg","r"); dat=f.read; f.close;;;;; p = SYSTEM.datadir+"/backups/config-corrupted_backup-"+Time.now.to_s.split(" ")[0..1].join(".").split(":").join(".").split("-").join(".")+".cfg.dat";;;;; f=File.open(p,"w"); f.write(dat); f.close;;;;; SYSTEM.writelog("Old config data was backedup to: "+p.to_s);;;;; rescue; SYSTEM.errorlog("Config repair failed to backup old config data.");;;;; end;;;;; @config=@default_config ; @loaded_config = "config.cfg";;;;; self.save_config ;;;;; end;;;;; ;;;;; def read_config *args;;;;; if args[0].to_s == ""; raise "Input requires String"; else; path = args[0].to_s; end;;;;; if File.file?(path); path = path;;;;; elsif File.file?(SYSTEM.cfgdir+"/"+path); path = SYSTEM.cfgdir+"/"+path;;;;; elsif File.file?(SYSTEM.cfgdir+"/"+path+".cfg"); path = SYSTEM.cfgdir+"/"+path+".cfg";;;;; elsif File.file?(SYSTEM.cfgdir+"/"+path+".config"); path = SYSTEM.cfgdir+"/"+path+".config";;;;; else; raise "No such file: "+path;;;;; end;;;;; begin; f = File.open(path,"r"); dat=f.read;;;;; rescue; raise "File read failed: "+ path.to_s;;;;; end;;;;; if dat.length>0;;;;; begin; data = eval(dat);;;;; if args.length == 1; return data;;;;; elsif args.length == 2 and args[1].is_a?(Integer);;;;; return data[args[1]];;;;; elsif args.length == 2 and args[1].is_a?(Range);;;;; return data[args[1]];;;;; else; raise "Invalid arguement, second arguement should be Integer or Range.";;;;; end;;;;; rescue; raise "Config eval failed: "+path.to_s;;;;; end;;;;; else; raise "Config file was empty: "+path.to_s;;;;; end;;;;; end;;;;; ;;;;; def write_config *args;;;;; if args[0].to_s == ""; raise "Input requires String"; else; path = args[0].to_s; end;;;;; if File.file?(path); path = path;;;;; elsif File.file?(SYSTEM.cfgdir+"/"+path); path = SYSTEM.cfgdir+"/"+path;;;;; elsif File.file?(SYSTEM.cfgdir+"/"+path+".cfg"); path = SYSTEM.cfgdir+"/"+path+".cfg";;;;; elsif File.file?(SYSTEM.cfgdir+"/"+path+".config"); path = SYSTEM.cfgdir+"/"+path+".config";;;;; else; raise "No such file: "+path;;;;; end;;;;; if args[1].is_a?(Integer); pos = args[1];;;;; elsif args[1].is_a?(Range); pos = args[1];;;;; else; raise "Invalid input, second arguement requires Integer or Range.";;;;; end;;;;; if args.length == 3; value = args[2];;;;; else; raise "Error, third argument is required.";;;;; end;;;;; if File.file?(path) == false; raise "No such file: "+path.to_s;;;;; end;;;;; begin; f = File.open(path,"r"); dat=f.read;;;;; rescue; raise "File read failed: "+ path.to_s;;;;; end;;;;; begin; data=eval(dat);;;;; rescue; raise "Failed to read config: "+path.to_s;;;;; end;;;;; data[pos]=value;;;;; begin; f = File.open(path,"w"); f.write(data.to_s); f.close; return true;;;;; rescue; raise "File write failed: "+path.to_s;;;;; end;;;;; end;;;;; ;;;;; def remove_altconfig;;;;; if self.altconfig?;;;;; begin; File.delete(@cfgdir+"/altconfig.cfg"); return true;;;;; rescue; self.errorlog("Failed to delete altconfig file."); return false;;;;; end;;;;; else; return false;;;;; end;;;;; end;;;;; ;;;;; def create_preconfig *args ## config, integer;;;;; if args[0].is_a?(Array);;;;; if args[0].length != @config.length;;;;; raise "Given config array does not match system config array length.";;;;; end;;;;; else; raise "First arguement must be config array.";;;;; end;;;;; if args.length==1;;;;; cfgs=[];;;;; Dir.entries(@cfgdir)[2..-1].each { |i| if i.to_s.downcase[0..8]=="preconfig"; cfgs << i; end };;;;; i=cfgs.length;;;;; else;;;;; if args[1].is_a?(Integer) == false;;;;; raise "Second arguement is not an integer.";;;;; else;;;;; i=args[1].to_i;;;;; end;;;;; end;;;;; path=@cfgdir+"/preconfig"+i.to_s+".cfg";;;;; f=File.open(path,"w"); f.write(args[0].to_s); f.close;;;;; return i;;;;; end;;;;;;;;;;;;;;; def load_cache;;;;; end;;;;;;;;;; def save_cache;;;;; end;;;;;;;;;; def repair_cache;;;;;;;;;; end ;;;;;;;;;; ## LOAD/RUN METHODS;;;;; ;;;;; ## figure out what the fuck we want shortcuts to be, ideally cmd/host script files;;;;; def shortcut(str) ## load ruby files in a new ruby interpreter window;;;;; # if str[-3..-1].to_s.downcase!=".rb";str=str.to_s+".rb";end;;;;; # if File.exist?(@homedir+"/shortcuts/"+str.to_s+".rb");;;;; # odir=Dir.getwd;;;;; # Dir.chdir(@homedir+"/shortcuts");;;;; # system("start "+str.to_s+".rb");;;;; # Dir.chdir(odir);;;;; # return true ;;;;; # else;return false;;;;; # end;;;;; end;;;;; ;;;;; ;;;;; ## load classes ;;;;; def load_classdir *args;;;;; load_classes = [] ; loaded_classes = [];;;;; if args.length == 0;;;;; Dir.entries(@classdir).each do |f|;;;;; if f.to_s == "." or f.to_s == ".." ; next ; end;;;;; if File.file?(@classdir + "/" + f.to_s) and f.to_s.downcase[-3..-1] == ".rb" ; load_classes << f.to_s ; end;;;;; end;;;;; else ; load_classes = args[0];;;;; end;;;;; if load_classes.length == 0;;;;; SYSTEM.writelog("Rubin.load_classdir: No classes were found to be loadable.");;;;; return 0;;;;; end;;;;; load_classes.each do |c|;;;;; begin;;;;; begin ; f = File.open(@classdir + "/" + c.to_s, "r") ; script = f.read ; f.close;;;;; rescue ; raise "Failed to read file.";;;;; end;;;;; MAIN.instance_eval(script) ; @loaded_classes << c.to_s ; loaded_classes << c.to_s ;;;;; SYSTEM.writelog("Rubin.load_classdir: Loaded class file: " + c.to_s);;;;; rescue => e;;;;; SYSTEM.errorlog("Rubin.load_classdir: Class file produced an exception: " + c.to_s + ", Error: " + e.to_s + "\n" + e.backtrace.join("\n"));;;;; end;;;;; end;;;;; if loaded_classes.length > 0 ; if $debug ; puts "Loaded classes: " + loaded_classes.to_s ; end ; end;;;;; return loaded_classes;;;;; end;;;;; alias :load_classes :load_classdir;;;;;;;;;;;;;;; ## note: the script can see instance variables like args and aargs;;;;; ## we added options for internal/external and passing args, finnaly the name should have an extension for external only scripts;;;;; def runs *args ## name, *args, external;;;;; if args.length == 0 or args[0].to_s.length == 0; raise "Invalid arguments, requires String, scriptname."; end ;;;;; if args.length > 1; aargs = args[1]; else; aargs = []; end;;;;; if args.length > 2 and args[2] == true; external = true; else; external = false; end;;;;;;;;;; scriptname = args[0].to_s;;;;; s=@datadir+"/scripts/"+scriptname.to_s;;;;; if s.to_s.downcase.end_with?(".rb") == false; s=s+".rb";end;;;;;;;;;; #puts "LAUNCHING: "+s.to_s;;;;; ## adjust this to check if a script is an external (script.ext.rb), for extrenal scripts, ignore arguement val for ext unless debug mode is on;;;;;;;;;; if external == false ## load script in current ruby;;;;; begin;str=File.read(s);;;;; self.writelog("Rubin.runs: running file: "+s.split("/")[-1]);;;;; begin; res = self.instance_eval(str) ; @loaded_files << scriptname; @loaded_scripts << scriptname;;;;; rescue => e; self.writelog("Rubin.runs: File produced an exception: "+s.split("/")[-1]+" Error: "+e.to_s+" ; "+e.backtrace.join("\n")); return e;;;;; end;;;;; if res.to_s != ""; return res;;;;; else; return true;;;;; end;;;;; rescue; self.writelog("Rubin.runs: Failed to access file: "+s.to_s); return false;;;;; end;;;;; else ##create a new windows with cmd.exe, run ruby and pass shortcut as script;;;;; odir=Dir.getwd; Dir.chdir(@homedir+"/shortcuts");;;;; aargs = aargs.join(" ");;;;; cmd = "start "+s.to_s+" - "+aargs.to_s;;;;; #puts "ABOUT TO MAKE SYSTEM CALL: "+cmd.to_s;;;;; system(cmd);;;;; Dir.chdir(odir);;;;; return true ;;;;; end;;;;; end;;;;; ;;;;; def run *args ## appname, [args];;;;; if args.length == 0 or args[0].to_s == "" ; raise "Rubin.run: Invalid arguments: ('appname',['args'])" ; end;;;;; if SYSTEM.apps?(args[0].to_s) == false ; SYSTEM.errorlog("Rubin.run: Attempted to load invalid app: "+args[0].to_s) ; raise "No such app: "+args[0].to_s ; end;;;;; ;;;;; if args[0].to_s.downcase[-3..-1] == ".rb" ; appname = args[0].to_s[0..-4];;;;; else ; appname = args[0] ; args[0] = args[0] + ".rb";;;;; end;;;;; ;;;;; ;;;;; if File.file?(@appdir + "/" + args[0].to_s);;;;; type = "file" ; entrypoint = @appdir + "/" + args[0].to_s;;;;; elsif File.directory?(@appdir + "/" + args[0].to_s + "/" + args[0].to_s + ".rb");;;;; type = "dir" ; entrypoint = @appdir + "/" + args[0].to_s + "/" + args[0].to_s + ".rb";;;;; else;;;;; SYSTEM.errorlog("Rubin.run: App file disapeared before it could be loaded: "+args[0].to_s);;;;; raise "Rubin.run: The app file disapeared: "+args[0].to_s;;;;; end;;;;; ;;;;; @app = nil ; @appshell = false ; @post_init = false ; @stopped = false;;;;; ;;;;; begin ; f = File.open(entrypoint,"r") ; source = f.read ; f.close;;;;; rescue; SYSTEM.errorlog("Rubin.run: Failed to read app file: "+entrypoint) ; raise "Rubin.run: Failed to read app file: "+entrypoint;;;;; end;;;;; ;;;;; SYSTEM.writelog("Rubin.run: Prepairing to run app: "+args[0].to_s);;;;; ;;;;; begin;;;;; SYSTEM.instance_eval(source);;;;; SYSTEM.writelog("Rubin.run: App run success: "+args[0].to_s);;;;; ;;;;; @loaded_files << args[0].to_s;;;;; rescue => e;;;;; SYSTEM.errorlog("Rubin.run: " + args[0].to_s + " : App encountered an exception: "+ e.to_s + "\n" + e.backtrace.join("\n"));;;;; raise "Rubin.run: " + args[0].to_s + " : Encountered an exception: " + e.to_s + "\n" + e.backtrace.join("\n");;;;; end;;;;; ;;;;; if @app == nil ; return true; end;;;;; @apps << [appname,rand(1000000),Time.now,@app] ;;;;; @loaded_apps<<[appname,Time.now.to_s];;;;; app_obj = @app ; @app = nil;;;;; ;;;;; if app_obj.methods.include?(:post_initialize) and @post_init != true;;;;; begin ; app_obj.post_initialize ; SYSTEM.writelog("Rubin.run " + args[0].to_s + " post_init was run.");;;;; rescue => e ; SYSTEM.errorlog("Rubin.run " + args[0].to_s + " : App post_init encountered an exception: " + e.to_s + "\n" + e.backtrace.join("\n")) ; return false;;;;; end;;;;; end;;;;; ;;;;; if @appshell == true;;;;; SYSTEM.writelog("Rubin.run: App " + appname + " is now the shell context.");;;;; SYSTEM.shell.start(app_obj);;;;; @appshell=false;;;;; end ;;;;; ;;;;; return app_obj;;;;; end;;;;; ;;;;; ################################################################################################################################################# ;;;;; #################################################################################################################################################;;;;; ## ect methods ;;;;; ;;;;; def help *args ## obj, keyword;;;;; # p = $datadir+"/RubinManual";;;;; # if File.directory?(p) == false; raise "There is no manual dir." end;;;;; # if args.length == 1 and args[0].to_s.length > 0; c = ""; k = args[0].to_s;;;;; # elsif args.length == 2; c = args[0].class.to_s; k = args[1].to_s;;;;; # else; raise "Invalid arguments.";;;;; # end;;;;; # if c.to_s == ""; else; if c.include?("::"); c = c.split("::").join(";"); end; end;;;;; # if k.end_with?("!"); k = k[0..-2].to_s+"e"; end;;;;; # if k.end_with?("?"); k = k[0..-2].to_s+"q"; end;;;;; # if c.to_s == ""; lookup = k.to_s;;;;; # else; lookup = c.to_s+"."+k.to_s;;;;; # end;;;;; # path = p+"/"+lookup.to_s+".txt" ;;;;; # if File.file?(path) == false; raise "Invalid object or keyword."; end;;;;; # begin; f=File.open(path,"r"); dat=f.read; f.close;;;;; # rescue; raise "Fialed to read help file.";;;;; # end;;;;; # puts "";;;;; # puts dat.to_s;;;;; # puts "";;;;; # return nil;;;;; end;;;;; ;;;;; def export_classes *args;;;;; if args[0].to_s == ""; raise ""; else; name = args[0].to_s end;;;;; if name.to_s.length==0;name="untitled-"+Time.now.to_s+"-definitions.rb";;;;; else; name=name.to_s; if name.downcase.end_with?(".rb") == false ; name = name+".rb"; end;;;;; end;;;;; if args.length == 1; path=@datadir+"/definitions/"+name.to_s;;;;; elsif args.length == 2 and File.directory?(args[1].to_s); path=args[1].to_s+"/"+name.to_s;;;;; end;;;;; if Dir.entries(@classdir).length>2;;;;; classes=Dir.entries(@classdir)[2..-1];;;;; files=[];;;;; namesep="#5#;#6#;#9#;#9#;#4#"+";#5#;#6#;#7#;#9#;#6#;#4#";;;;; filesep="#8#;#3#;#5#;#3#;#1#"+";#8#;#3#;#5#;#3#;#8#;#5#";;;;; first=[];;;;; classes.each { |c| ;;;;; if c.to_s.downcase=="self.rb"; f=File.open(@classdir+"/"+c,"r");first<<["#"+c,f.read];f.close;;;;; else;f=File.open(@classdir+"/"+c,"r");files<<["#"+c,f.read];f.close ;;;;; end;;;;; };;;;; if first.length >0 ;files.each{|f| first << f};files=first;end;;;;; joined=[]; files.each {|f| joined<< f[0].to_s+namesep+f[1].to_s};;;;; files=joined.join(filesep);;;;; f=File.open(path,"w");f.write(files);f.close;;;;; return true;;;;; else;return "$classdir is empty?";;;;; end;;;;; end;;;;; ;;;;; #import_classes("E:/rubin/data/definitions/ossy.rb");;;;; def import_classes(path);;;;; if path.downcase.end_with?(".rb") == false; path = path+".rb"; end;;;;; if File.file?(path); dir = Dir.getwd; fpath = dir+"/"+path;;;;; elsif File.file?(@classdir+"/"+path);dir = @classdir; fpath = dir+"/"+path;;;;; elsif File.file?(@datadir+"/definitions/"+path); dir = @datadir+"/definitions"; fpath = dir+"/"+path;;;;; else; raise "Unable to locate definitons file.";;;;; end;;;;; c = Dir.entries(dir); c.delete("."); c.delete("..");;;;; if c.length > 0;;;;; f=File.open(fpath,"r");definition=f.read;f.close;;;;; namesep="#5#;#6#;#9#;#9#;#4#"+";#5#;#6#;#7#;#9#;#6#;#4#";;;;; filesep="#8#;#3#;#5#;#3#;#1#"+";#8#;#3#;#5#;#3#;#8#;#5#";;;;; joined_files=definition.split(filesep); files=[];;;;; joined_files.each {|f| files<<f.split(namesep)};;;;; files.each {|f|;;;;; if f.length==0 or f[0].to_s.length == 0; next; end;;;;; nfpath=@classdir+"/"+f[0].to_s[1..-1];;;;; ff=File.open(nfpath,"w");ff.write(f[1].to_s);ff.close;;;;; };;;;; return true;;;;; else;return "Unable to find class files.";;;;; end;;;;; end;;;;;;;;;; ## SHORTCUT METHODS AND ALIASES;;;;; def restart_link; self.restart(true); end;;;;; def shutdown_link; self.shutdown(true,true); end; ;;;;; #def hardrestart_link; self.hard_restart(true); end;;;;; #def hardshutdown_link; self.hard_shutdown(true); end; ;;;;;;;;;; ##generate installer then move it to desktop;;;;; def spawn;;;;; if HOST_OS == "linux"; return "I havent been coded to do this on linux yet. Try Windows NT.";;;;; elsif HOST_OS == "Windows_NT";;;;; gotodir="C:/users/"+ENV["USERNAME"]+"/desktop";;;;; install.generate_installer;;;;; f=File.open(@datadir+"/backups/rubin_installer.rb","r"); dat=f.read; f.close;;;;; f=File.open(gotodir+"/rubin_installer.rb","w"); f.write(dat); f.close;;;;; return "The installer was made and put on your desktop.";;;;; else;;;;; return "Cannot proceed on unknown host: "+HOSt_OS.to_s;;;;; end;;;;; end;;;;; ;;;;; alias :rr :restart_link;;;;; alias :ee :shutdown_link;;;;; alias :ii :spawn;;;;; #alias :hr :hardrestart_link;;;;; #alias :hs :hardshutdown_link;;;;;;;;;; ####################################################################################################################################;;;;; ## Embedded System Components below VVVVVVVVVVVVVVVVVVVV;;;;; ;;;;; ## NEW DAEMOND r1.0.5;;;;;;;;;; class SystemDaemond;;;;; def initialize;;;;; @init = false;;;;; @shutdown_behavior = false;;;;; @daemond_delay = 1.0;;;;; @daemond_auto = false;;;;; @daemond_file = nil;;;;; @scope = self ; @daemond = self;;;;; @threadpool = [];;;;; @gravepool = [];;;;; @lockpool = false;;;;; @thread_limit = 999999;;;;; @thread_object = nil;;;;; @pool_cleaner_thread = nil;;;;; @pool_cleaner = false;;;;; end;;;;; ;;;;; def post_initialize;;;;; if @init == true ; return false ; end ; @init = true;;;;; ;;;;; i = SYSTEM.config("DaemondDelay");;;;; if i.to_i > 0 ; @daemond_delay = i.to_i ; @daemond_auto = true ; end;;;;; ;;;;; if @daemond_auto == false ; return true ; end;;;;; if File.file?(SYSTEM.sysdir + "/daemond.rb") == false ; return true ; end;;;;; ;;;;; begin ; f = File.open(SYSTEM.sysdir + "/daemond.rb","r") ; script = f.read ; f.close;;;;; rescue ; SYSTEM.errorlog("Rubin::SystemDaemond.post_initialize: Unable to read daemond file.") ; return false;;;;; end;;;;; ;;;;; script.split("###;###;###;###;###").each do |s|;;;;; lines = s.split("\n");;;;; lines.delete("") ;;;;; name = "" ; parent = "";;;;; script_lines = [];;;;; ;;;;; lines.each do |l|;;;;; if (l.delete(" ")).length == 0 ; next ; end;;;;; if l[0] == "#";;;;; if l[0..6].to_s.downcase == "##name=" ; name = l[7..-1];;;;; elsif l[0..8].to_s.downcase == "##parent=" ; parent = l[9..-1];;;;; else ; next;;;;; end;;;;; else;;;;; script_lines << l;;;;; end;;;;; end;;;;; ;;;;; script = script_lines.join("\n");;;;; ;;;;; if script_lines.length == 0 or script.length == 0;;;;; SYSTEM.errorlog("Rubin::SystemDaemond.post_initialize: Daemond file contained an empty block, it was skipped.") ; next;;;;; else;;;;; SYSTEM.writelog("Rubin.SystemDaemond.post_initialize: Spawning daemond file thread: "+name.to_s);;;;; self.spawn_thread(name,script,parent);;;;; end ;;;;; end;;;;; ;;;;; self.spawn_pool_cleaner;;;;; ;;;;; return true;;;;; end;;;;; ;;;;; def spawn_thread *args ## ("name","script",Parent);;;;; if args[1].to_s == "" ; SYSTEM.errorlog("Rubin::SystemDaemond.spawn_thread: Attempted to spawn empty thread.") ; return false ; end;;;;; if @threadpool.length >= @thread_limit ; SYSTEM.errorlog("Rubin::SystemDaemond.spawn_thread: Cannot spawn thread, thread limit reached. " + args[0].to_s) ; return false ; end;;;;; if @lockpool == true ; return nil ; end;;;;; ;;;;; name = args[0].to_s;;;;; id = (@threadpool.length + 1).to_s;;;;; script = args[1].to_s;;;;; if args[2] == nil ; parent = "";;;;; elsif args[2].is_a?(String) ; parent = args[2];;;;; else ; parent = args[2].class.to_s;;;;; end;;;;; ;;;;; header = "@thread_object = Thread.new{" ; footer = "}";;;;; body = header + script + footer;;;;; ;;;;; begin ; @lockpool = true ; @thread_object = nil;;;;; @scope.instance_eval(body);;;;; @threadpool << [name,id,parent,@thread_object];;;;; @lockpool = false ; @thread_object = nil ; return id;;;;; rescue => e;;;;; SYSTEM.errorlog("Rubin::SystemDaemond.spawn_thread: Thread script encountered an exception: "+e.to_s+"\n"+e.backtrace.join("\n"));;;;; @lockpool = false ; @thread_object = nil ; return false;;;;; end;;;;; end;;;;;;;;;; def running?;;;;; if @threadpool.length == 0 ; return false ; end;;;;; found_running = false;;;;; @threadpool.each do |t| ; begin ; if t[3].alive? == true ; found_running = true ; break ; end ; rescue ; next ; end ; end;;;;; return found_running;;;;; end;;;;; ;;;;; def shutdown;;;;; if @shutdown_behavior == true ; return false ; end;;;;; @shutdown_behavior = true ; @lockpool = true;;;;; if self.running?;;;;; @threadpool.each do |t|;;;;; begin ; t[3].kill ; rescue ; next ; end;;;;; @gravepool << t;;;;; end;;;;; @threadpool = [];;;;; end;;;;; return true;;;;; end;;;;; ;;;;; def spawn_pool_cleaner;;;;; if @pool_cleaner_thread.is_a?(Thread) ; if @pool_cleaner_thread.alive? == true ; return false ; end ; end;;;;; ;;;;; @pool_cleaner_thread = Thread.new {;;;;; @pool_cleaner = true;;;;; loop do;;;;; if @pool_cleaner == false ; break ; end;;;;; @threadpool.each do |t|;;;;; if t[3].alive? == false;;;;; @gravepool << t;;;;; @threadpool.delete(t);;;;; end;;;;; end;;;;; sleep @daemond_delay.to_f;;;;; end;;;;; @pool_cleaner = false;;;;; };;;;; ;;;;; return true;;;;; end;;;;; ;;;;; def killthread(id);;;;; thread = false;;;;; @threadpool.each do |t| ; if t[1].to_s == id.to_s ; thread = @threadpool.index(t) ; break ; end ; end;;;;; if thread == false ; return false ; end;;;;; if @threadpool[thread].alive? == false ; return nil ; end;;;;; begin;;;;; @threadpool[thread].kill;;;;; @gravepool << @threadpool[thread];;;;; @threadpool.delete_at(thread);;;;; return true;;;;; rescue ; SYSTEM.errorlog("Rubin::SystemDaemond.killthread: Invalid object in threadpool at index: " + thread.to_s) ; return false;;;;; end;;;;; end;;;;; ;;;;; def alive?(id);;;;; thread = false;;;;; @threadpool.each do |t| ; if t[1].to_s == id.to_s ; thread = @threadpool.index(t) ; break ; end ; end;;;;; if thread == false ; raise "Rubin::SystemDaemond.alive?: No such thread id: "+id.to_s ; end;;;;; begin ; return @threadpool[thread].alive?;;;;; rescue ; SYSTEM.errorlog("Rubin::SystemDaemond.alive?: Invalid object in threadpool at index: "+thread.to_s) ; return nil;;;;; end;;;;; end;;;;; ;;;;; def threadpool ; return @threadpool ; end;;;;; def lockpool *args;;;;; if args.length == 0 ; return @lockpool;;;;; elsif args[0].to_s.downcase == "true" ; @lockpool = true;;;;; elsif args[0].to_s.downcase == "false" ; @lockpool = false;;;;; else ; raise "Rubin::SystemDaemond.lockpool: Invalid arguements: Only takes true/false/nil";;;;; end;;;;; end;;;;; ;;;;; end;;;;; ;;;;; ##################################################################################################################################;;;;; ## SystemShell;;;;; ;;;;; class SystemShell;;;;; def initialize ;;;;; @main_context = MAIN;;;;; @system_context = SYSTEM;;;;; @shell_context = self;;;;; @context_history = [];;;;; @input_history = [];;;;; @session_history = [];;;;; @session_logging = false;;;;; @logdir = SYSTEM.logdir + "/systemshellmajor.log";;;;; @current = nil;;;;; @current_sessions = [];;;;; end;;;;; ;;;;; def post_initialize;;;;; @session_logging = SYSTEM.config("ShellSessions");;;;; if File.file?(@logdir) == false ; f = File.open(@logdir,"w") ; f.close ; end;;;;; if @session_logging == true;;;;; f = File.open(@logdir,"r") ; log = f.read ; f.close;;;;; if log.length > 0;;;;; lines = log.split("\n") ; lines.delete("");;;;; if lines[-1].to_s != "####################SESSION_SEP####################";;;;; f = File.open(@logdir,"a") ; f.write("####################SESSION_SEP####################\n") ; f.close;;;;; end;;;;; end;;;;; end;;;;; end;;;;;;;;;; def sessions ; return @current_sessions ; end;;;;; def current_session ; return @current ; end;;;;; ;;;;; def stop *args;;;;; if args.length == 0;;;;; if @current_sessions.length > 0 and @current.is_a?(Integer);;;;; @current_sessions[@current][3] = false ; return true;;;;; else ; return false;;;;; end;;;;; elsif args.length > 0 and args[0].is_a?(Integer);;;;; if args[0] <= (@current_sessions.length-1);;;;; @current_sessions[args[0]][3] = false ; return true;;;;; else ; return false;;;;; end;;;;; end;;;;; end;;;;;;;;;; def start *args;;;;; if args.length > 0 and args[0].to_s == "session";;;;; session = args[1] ; if args.length > 2 ; context = args[2] ; else ; context = @system_context ; end;;;;; self.enter_session(session,context);;;;; elsif args.length == 1 ; self.enter_repl_loop(args[0]);;;;; elsif args.length == 0 ; self.enter_repl_loop;;;;; end;;;;; end;;;;;;;;;; def enter_repl_loop *args;;;;; cid = 0 ; state = "";;;;; if args.length == 0 ; context = @system_context ; else ; context = args[0] ; end;;;;; @current_sessions << [context,cid,state,true] ; @session_history << [];;;;; session_index = @current_sessions.index(@current_sessions[-1]);;;;; loop do;;;;; if @current_sessions[session_index][3] != true ; break ; end;;;;; result = nil ; @current = session_index;;;;; print @current_sessions[session_index][0].class.to_s+":"+@current_sessions[session_index][1].to_s+"<< ";;;;; @current_sessions[session_index][2] = "getting input";;;;; input = gets.chomp ; @input_history << input ; @session_history[session_index] << input;;;;; @current_sessions[session_index][2] = "processing input";;;;; if input.to_s == "exit";;;;; @current_sessions[session_index][3] = false;;;;; result = "Exiting shell.";;;;; elsif input.to_s[0..8] == "*context=" and input.to_s.length > 9;;;;; begin;;;;; new_context = @current_sessions[session_index][0].instance_eval(input.to_s[9..-1]);;;;; @context_history << @current_sessions[session_index][0];;;;; @current_sessions[session_index][0] = new_context;;;;; result = "Shell context was changed to: " + new_context.class.to_s;;;;; rescue;;;;; result = "Failed to set shell context.";;;;; end;;;;; elsif input.to_s == "*cls" ; system("CLS") ; result = :NO_RESULT;;;;; elsif input.to_s[0] == "*" and input.to_s.length > 1;;;;; begin ; result = @current_sessions[session_index][0].instance_eval("`"+input[1..-1]+"`") ; if result.to_s == "" ; result = :NO_RESULT ; end;;;;; rescue ; result = "An error occured while making system call.";;;;; end;;;;; elsif input.to_s[0..1] == "<*";;;;; begin ; system(input[2..-1]) ; result = "System command was executed.";;;;; rescue ; result = "System command could not be executed.";;;;; end;;;;; else;;;;; begin ; result = @current_sessions[session_index][0].instance_eval(input);;;;; rescue => e ; result = "Exception: " + e.to_s;;;;; end;;;;; end;;;;; if result != :NO_RESULT;;;;; print @current_sessions[session_index][0].class.to_s + ":" + @current_sessions[session_index][1].to_s + ">> " + result.to_s + "\n" ;;;;;; #@session_history[session_index] << result;;;;; end;;;;; @current_sessions[session_index][1] += 1;;;;; ;;;;; if @session_logging == true;;;;; begin ; f = File.open(@logdir,"a") ; f.write(input+"\n") ; f.close;;;;; rescue ; SYSTEM.errorlog("Rubin::SystemShell.enter_repl_loop: Failed to write to shell major log file: " + input.to_s);;;;; end;;;;; end;;;;; ;;;;; @current_sessions[session_index][2] = "idle" ;;;;; end;;;;; @current_sessions.delete_at(session_index);;;;; @session_history.delete_at(session_index);;;;; return nil;;;;; end;;;;; ;;;;; def enter_session *args ##session_file/[], context;;;;; if args.length > 0 and args[0].is_a?(Array) ; session = args[0];;;;; elsif args.length > 0 and args[0].is_a?(String);;;;; if args[0].include?("/") == false ; args[0] = SYSTEM.dirs("datadir") + "/" + args[0] ; end;;;;; begin ; f = File.open(args[0],"r") ; session = f.read.split("\n") ; f.close ; session.delete("");;;;; rescue ; raise "Rubin::SystemShell.enter_session: Unable to read session file: " + args[0].to_s;;;;; end;;;;; else ; raise "Rubin::SystemShell.enter_session: Invalid arguements: Requires a filepath to saved session or array of a session.";;;;; end;;;;; ;;;;; if args.length > 1 ; context = args[1] ; else ; context = @system_context ; end;;;;; ;;;;; cid = 0 ; state = "";;;;; @current_sessions << [context,cid,state,true];;;;; session_index = @current_sessions.index(@current_sessions[-1]) ; @current = session_index;;;;; ;;;;; session.each do |i|;;;;; if @current_sessions[session_index][3] != true ; break ; end;;;;; input = i;;;;; print @current_sessions[session_index][0].class.to_s + ":" + @current_sessions[session_index][1].to_s + "<< " + input.to_s + "\n";;;;; @current_sessions[session_index][2] = "processing input";;;;; ;;;;; if input.to_s == "exit";;;;; @current_sessions[session_index][3] = false;;;;; result = "Exiting shell.";;;;; elsif input.to_s[0..8] == "*context=" and input.to_s.length > 9;;;;; begin;;;;; new_context = @current_sessions[session_index][0].instance_eval(input.to_s[9..-1]);;;;; @context_history << @current_sessions[session_index][0];;;;; @current_sessions[session_index][0] = new_context;;;;; result = "Shell context was changed to: " + new_context.class.to_s;;;;; rescue;;;;; result = "Failed to set shell context.";;;;; end;;;;; elsif input.to_s == "*cls" ; system("CLS") ; result = :NO_RESULT;;;;; elsif input.to_s[0] == "*" and input.to_s.length > 1;;;;; begin ; result = @current_sessions[session_index][0].instance_eval("`"+input[1..-1]+"`") ; if result.to_s == "" ; result = :NO_RESULT ; end;;;;; rescue ; result = "An error occured while making system call.";;;;; end;;;;; else;;;;; begin ; result = @current_sessions[session_index][0].instance_eval(input);;;;; rescue => e ; result = "Exception: " + e.to_s;;;;; end;;;;; end;;;;; if result != :NO_RESULT;;;;; print @current_sessions[session_index][0].class.to_s + ":" + @current_sessions[session_index][1].to_s + ">> " + result.to_s + "\n" ;;;;;; end ;;;;; @current_sessions[session_index][1] += 1;;;;; @current_sessions[session_index][2] = "idle";;;;; end;;;;; ;;;;; @current_sessions.delete_at(session_index);;;;; return nil;;;;; end;;;;; ;;;;; def save_session *args ## file_name, session_index;;;;; if args.length == 0 or args[0].to_s == "" ; raise "Rubin::SystemShell.save_session: Invalid arguments, requires a file name." ; end ;;;;; if args[0].to_s.include?("/") ; filename = args[0].to_s;;;;; else ; filename = SYSTEM.dirs("datadir") + "/" + args[0].to_s;;;;; end;;;;; if args.length == 1 ; index = @current.to_i;;;;; elsif args.length > 1 and args[1].is_a?(Integer) ; index = args[1];;;;; else ; raise "Rubin::SystemShell.save_session: Invalid argument, must be integer. (index of @current_sessions)";;;;; end;;;;; if index.to_i > (@current_sessions.length-1) ; raise "Rubin::SystemShell.save_session: Invalid session index." ; end;;;;; session = @session_history[index];;;;; if session.length == 0 ; raise "Rubin::SystemShell.save_session: Session is empty, it cannot be saved." ; end;;;;; session.each do |i| ; if i.to_s.include?(".save_session") ; session.delete_at(session.index(i)) ; end ; end;;;;; begin ; f = File.open(filename,"w") ; f.write(session.join("\n")) ; f.close ; return true;;;;; rescue ; raise "Rubin::SystemShell.save_session: Unable to create file with this name: "+filename.to_s ; return false;;;;; end;;;;; end;;;;; ;;;;; def load_session(path);;;;; if path.include?("/") == false and File.file?(SYSTEM.dirs("datadir")+"/"+path);;;;; path = SYSTEM.dirs("datadir") + "/" + path.to_s;;;;; elsif File.file?(path.to_s) ; path = path.to_s;;;;; else ; raise "Rubin::SystemShell.load_session: No such file: "+path;;;;; end;;;;; begin ; f = File.open(path,"r") ; session = f.read.split("\n") ; f.close ; session.delete("");;;;; rescue ; raise "Rubin::SystemShell.load_session: Unable to read file: "+path;;;;; end;;;;; return session;;;;; end;;;;; ;;;;; end;;;;;;;;;; ################################################################################################################################;;;;; ################################################################################################################################;;;;; ## instance;;;;; ;;;;; class Instance;;;;; def initialize;;;;; @id=INSTANCE;;;;; end;;;;; ;;;;; def locals?;;;;; i=Dir.entries(SYSTEM.datadir+"/sys/instance");;;;; if i.length>0;;;;; l=[];fl=[];;;;; i.each do |f|;;;;; if f.to_s.downcase[-4..-1]==".dat" and f.to_s[0..-5].delete("0123456789").length==0;;;;; l<<f[0..-5];;;;; end;;;;; end;;;;; if l.length>0;;;;; l.each do |ll|;;;;; f=File.read(SYSTEM.datadir+"/sys/instance/"+ll.to_s+".dat");;;;; str=Time.stamp(f);;;;; sec=Time.now-str;;;;; if sec.to_i<30;;;;; fl<<ll;;;;; end;;;;; end;;;;; return fl;;;;; else; return [];;;;; end;;;;; else; return [];;;;; end;;;;; end;;;;; ;;;;; def id ; return INSTANCE ; end;;;;; ;;;;; def pop *args ;;;;; SYSTEM.host.launch_new(SYSTEM.homedir+"/launch.rb");;;;; end;;;;; ;;;;; def spawn *args;;;;; str = args[0].to_s;;;;; str = "`start ruby \"launch.rb\" - "+str+"`";;;;; eval(str);;;;; end;;;;; ;;;;;end;;;;;;;;;; ################################################################################################################################;;;;; ################################################################################################################################;;;;; ## app controller ## eventually we will migrate the load app method here, maybe;;;;; ;;;;; class Apps;;;;; def initialize;;;;; end;;;;; ;;;;; def apps; return SYSTEM.instance_variable_get("@apps"); end;;;;;;;;;; def running?;;;;; apps = SYSTEM.instance_variable_get("@apps");;;;; if apps.length == 0 ; return [] ; end;;;;; info = [] ; apps.each { |a| info << [a[0].to_s,a[1].to_s]};;;;; return info;;;;; end;;;;;;;;;; def get(id);;;;; apps = SYSTEM.instance_variable_get("@apps");;;;; if apps.length == 0 ; return false ; end;;;;; found = false ; apps.each do |a| ; if a[1].to_s == id.to_s ; found = a[3] ; break ; end ; end;;;;; return found;;;;; end;;;;; ;;;;; def get_info(id);;;;; apps = SYSTEM.instance_variable_get("@apps");;;;; if apps.length == 0 ; return false ; end;;;;; found = false ; apps.each do |a| ; if a[1].to_s == id.to_s ; found = a ; break ; end ; end;;;;; return found ;;;;; end;;;;; ;;;;; end;;;;; ;;;;; ################################################################################################################################;;;;; ################################################################################################################################;;;;; ## HostManager;;;;; ;;;;; class Host_Manager;;;;; def initialize;;;;; @host_os = "";;;;; ;;;;; @host_name = "";;;;; @user_name = "";;;;; @autostart_dir = "";;;;; @host_home = "" #C:/;;;;; ;;;;; @host_controller = "";;;;; end;;;;; ;;;;; def post_initialize;;;;; host_os = ENV["os"].to_s.downcase;;;;; platform = RUBY_PLATFORM.to_s.downcase;;;;; ;;;;; if ENV["os"].to_s.downcase == "windows_nt" ; @host_os = "WINDOWS";;;;; elsif RUBY_PLATFORM.to_s.downcase == "x64-mingw-ucrt" ; @host_os = "WINDOWS";;;;; elsif RUBY_PLATFORM.to_s.downcase == "x86-mingw-ucrt" ; @host_os = "WINDOWS";;;;; ;;;;; else ; @host_os = "UNKNOWN" ;;;;; end;;;;; ;;;;; if @host_os == "WINDOWS";;;;; ##yeaaah boy we home n shieeet!;;;;; @host_name = ENV["COMPUTERNAME"];;;;; @user_name = ENV["USERNAME"];;;;; @host_home = ENV["SystemDrive"];;;;; ;;;;; elsif @host_os == "LINUX";;;;; ;;;;; ##doable but a pain in the ass;;;;; elsif @host_os == "ANDROID";;;;; ##not in a million years;;;;; else;;;;; ##unknown host;;;;; end;;;;; end;;;;; ;;;;; def os? ; return @host_os ; end;;;;; def name? ; return @host_name ; end;;;;; def user? ; return @user_name ; end;;;;; def drive? ; return @host_home ; end;;;;; ;;;;; def drives;;;;; if @host_os == "UNKNOWN" ; raise "Cannot perform this method on unsupported host system." ; end;;;;; dr = [];;;;; if @host_os == "WINDOWS";;;;; ["A:/","B:/","C:/","D:/","E:/","F:/","G:/","H:/","I:/","J:/","K:/","L:/","M:/","N:/","O:/","P:/","Q:/","R:/","S:/","T:/","U:/","V:/","W:/","X:/","Y:/","Z:/"].each do |v|;;;;; begin ; if File.directory?(v) ; dr << v ; end;;;;; rescue ; next;;;;; end;;;;; end;;;;; end;;;;; return dr;;;;; end;;;;; ;;;;; def procs;;;;; if @host_os == "UNKNOWN" ; raise "Cannot perform this method on unsupported host system." ; end;;;;; if @host_os == "WINDOWS";;;;; #Image Name, PID, Session Name, Session No., Mem Usage;;;;; str = `TASKLIST /FO CSV`;;;;; procs = [];;;;; str.each_line do |line|;;;;; # Skip the header line;;;;; next if line =~ /^"Image Name"/;;;;; # Extract the process information using a regular expression;;;;; match = line.match(/^"(.+?)","(\d+)","(.+?)","(\d+)","(\d+.*?)"/);;;;; if match;;;;; name = match[1];;;;; pid = match[2].to_i;;;;; session_name = match[3];;;;; session_n = match[4].to_i;;;;; mem_usag = match[5].to_i;;;;; procs << [name, pid, session_name, session_n, mem_usag];;;;; end;;;;; end;;;;; return procs;;;;; #elsif @host_os == "LINUX";;;;; else ; raise "Cannot perform this method, no support for this host: " + @host_os ;;;;; end;;;;; end;;;;; ;;;;; def memory_used;;;;; if @host_os == "WINDOWS";;;;; b=0 ; self.procs.each do |p| ; b += p[-1].delete(" ,K").to_i ; end;;;;; return b;;;;; else;;;;; end;;;;; end;;;;; ;;;;; def memory_installed ; raise "Not implemented yet!" ; end;;;;; ;;;;; def request(cmd);;;;; if cmd.to_s == "" ; return nil ; end;;;;; if @host_os == "WINDOWS" ; system(cmd.to_s);;;;; elsif @host_os == "LINUX" ; system(cmd.to_s);;;;; else ; raise "Cannot perform this method on unsupported host system.";;;;; end;;;;; return nil;;;;; end;;;;;;;;;; def call(cmd);;;;; if cmd.to_s == "" ; return nil ; end;;;;; if @host_os == "WINDOWS" ; self.instance_eval("`"+cmd.to_s+"`");;;;; elsif @host_os == "LINUX" ; self.instance_eval("`"+cmd.to_s+"`");;;;; else ; raise "Cannot perform this method on unsupported host system.";;;;; end;;;;; return nil;;;;; end;;;;;;;;;; def launch_new(path) ## run file in new window, used by system_restart;;;;; if @host_os == "WINDOWS";;;;; if File.file?(path);;;;; begin;;;;; cdir=Dir.getwd;;;;; Dir.chdir(path.to_s.split("/")[0..-2].join("/"));;;;; n=path.to_s.split("/")[-1];;;;; system("start "+n.to_s);;;;; Dir.chdir(cdir);;;;; return true;;;;; rescue; return false;;;;; end;;;;; else;return false;;;;; end;;;;; else ; raise "Cannot perform this method on unsupported host system.";;;;; end;;;;; end;;;;; ;;;;; def print_in_new_window(str);;;;; if @host_os == "WINDOWS" ; nstr = "`start ruby -e 'puts ARGV[1].to_s;system(\"PAUSE\")' - \""+str.to_s+"\"`" ; eval nstr ; return nil;;;;; else ; raise "Cannot perform method on unsupported host system.";;;;; end;;;;; end;;;;; ;;;;; def ruby_in_new_window(str) ## unused form of launch_new;;;;; if @host_os == "WINDOWS" ; str = str.to_s+"\n\n" ; nstr = "`start ruby -e 'instance_eval ARGV[1].to_s;system(\"PAUSE\")' - \""+str.to_s+"\"`" ; eval nstr ; return nil;;;;; else ; raise "Cannot perform method on unsupported host system.";;;;; end;;;;; end;;;;;;;;;; def get_window_title;;;;; raise "Not implemented yet!";;;;; end;;;;; ;;;;; def get_open_windows;;;;; raise "Not implemented yet!";;;;; end;;;;; ;;;;; def installed_programs *args;;;;; raise "Not implemented yet!";;;;; end;;;;; ;;;;; def get_executables *args;;;;; raise "Not implemented yet!";;;;; end;;;;; ;;;;; def get_ruby_procs;;;;; raise "Not implemented yet!";;;;; end;;;;; ;;;;; def switch_window *args;;;;; raise "Not implemented yet!";;;;; end;;;;; ;;;;; def toggle_start;;;;; raise "Not implemented yet!";;;;; end;;;;; ;;;;; end;;;;; ;;;;; ################################################################################################################################;;;;; ################################################################################################################################;;;;; #### Installation Manager;;;;; ;;;;; class Installation_Manager;;;;; def initialize;;;;; ##this package is fallback incase hidden internal was con configured with an index;;;;; @default_index_package=[["/rubin/system/rubin.rb",;;;;; "/rubin/system/daemond.rb",;;;;; "/rubin/system/definitions.rb",;;;;; "/rubin/launch.rb",;;;;; "/rubin/doc.txt",;;;;; "/rubin/launch irb.cmd",;;;;; "/rubin/launch rubin.cmd",;;;;; "/rubin/data/scripts/systemlogmonitor.rb",;;;;; "/rubin/data/scripts/logmonitor.rb",;;;;; "/rubin/data/scripts/unpackaged_installer_script.rb",;;;;; "/rubin/data/scripts/install_builder.rb",;;;;; "/rubin/data/scripts/file_backup.rb",;;;;; "/rubin/app/app_template.rb"],;;;;; ["/rubin/system",;;;;; "/rubin/bin",;;;;; "/rubin/app",;;;;; "/rubin/class",;;;;; "/rubin/data",;;;;; "/rubin/shortcuts",;;;;; "/rubin/data/appdata",;;;;; "/rubin/data/backups",;;;;; "/rubin/data/config",;;;;; "/rubin/data/definitions",;;;;; "/rubin/data/fileio",;;;;; "/rubin/data/logs",;;;;; "/rubin/data/scripts",;;;;; "/rubin/data/components",;;;;; "/rubin/data/sys",;;;;; "/rubin/data/sys/instance",;;;;; "/rubin/data/temp",;;;;; "/rubin/data/user"]];;;;; end;;;;; ;;;;; def post_initialize;;;;; index = SYSTEM.install.get_hidden_internal_data[2];;;;; if index == [] or index.to_s == "" or index == nil;;;;; ##index is not in hidat;;;;; else; @default_index_package = index;;;;; end;;;;; end ;;;;; ;;;;; def default_index; return @default_index_package; end;;;;; ;;;;; def id; return INSTALLATION_HEADER[5];;;;; end;;;;; def dir; return INSTALLATION_HEADER[1];;;;; end;;;;; ;;;;; ;;;;; def verify_dir;return INSTALLATION_HEADER[1].to_s.downcase==SYSTEM.homedir.to_s.downcase;;;;; end;;;;; def date; return INSTALLATION_HEADER[3];;;;; end;;;;; def version; return INSTALLATION_HEADER[2];;;;; end;;;;; def verify_installation_files(path);;;;; if path.to_s.downcase.split("/")[-1]=="rubin";;;;; if File.file?(path+"/system/rubin.rb");return true;end;;;;; end;;;;; return false;;;;; end;;;;; ;;;;; def default_build_package;;;;; a=self.default_index[0]; b=self.default_index[1];;;;; self.build_package(a,b);;;;; end;;;;; ;;;;; def make; return self.default_build_package; end;;;;; ;;;;; ## build a source package file from installed version;;;;; ## make sure this method updates hidden internal data in rubin.rb before its included;;;;; def build_package *args #(included_files,included_dir_paths);;;;; included_files=args[0];;;;; included_dir_paths=args[1];;;;; files_data=[];;;;; maindatasep="#1#::#1#::#0#::#0#::#0#"+"::#1#::#1#";;;;; filenamesep="#1#::#1#::#0#::#0#::#0#"+"::#0#::#1#";;;;; filesep="#1#::#1#::#0#::#0#::#0#"+"::#0#::#0#";;;;; index_sep="#1#::#0#::#0#::#0#::#0#"+"::#"+"0#::#1#";;;;; ##get index file paths;;;;; index_files=[];;;;; included_files.each do |f|;;;;; p=f.to_s.downcase.split("/rubin/")[-1];;;;; index_files << "/rubin/"+p;;;;; end;;;;; ## locations of actual resources;;;;; nincluded_files=[];;;;; included_files.each do |f|;;;;; p = f.to_s.downcase.split("/rubin/")[-1];;;;; nincluded_files << INSTALLATION_HEADER[1].to_s+"/"+p;;;;; end;;;;; included_files=nincluded_files;;;;; ##get index dir paths ;;;;; index_dirs=[];;;;; included_dir_paths.each do |d|;;;;; p=d.to_s.downcase.split("/rubin/")[-1];;;;; index_dirs << "/rubin/"+p;;;;; end;;;;; ##make index string;;;;; index1=index_files.join("?");;;;; index2=index_dirs.join("?");;;;; index=index1+"??"+index2;;;;; ## get data of all the files;;;;; files_data=[];;;;; included_files.each do |f|;;;;; f=File.open(f,"r");files_data << f.read ; f.close;;;;; end;;;;; ##combine files data with their index paths;;;;; nfiles_data=[];;;;; files_data.each do |fd|;;;;; i=files_data.index(fd);;;;; p=index_files[i.to_i];;;;; da=""+p.to_s+filenamesep+fd.to_s;;;;; nfiles_data << da;;;;; end;;;;; ;;;;; filespkg = nfiles_data.join(filesep);;;;; final_data = maindatasep.to_s + index.to_s + index_sep.to_s + filespkg.to_s;;;;; final_data=final_data.split("\n").join(";;"+";;;");;;;; d=SYSTEM.datadir+"/backups/installpackage.txt";;;;; f = File.open(d,"w");f.write(final_data); f.close;;;;; ;;;;; return "Your file was built: "+d.to_s;;;;;;;;;; end;;;;; ;;;;; ;;;;; def install_package(package,dir);;;;; if self.verify_installation_files(dir) == true ; raise "Rubin is already installed there."; end;;;;; if File.file?(package) == false; raise "Input file path is incorrect."; end;;;;; ;;;;; ##load data;;;;; f=File.open(package,"r"); data = f.read ; f.close;;;;; ;;;;; ##decode data;;;;; data=data.split(";;;"+";;").join("\n");;;;; ;;;;; maindatasep="#1#::#1#::#0#::#0#::#0#"+"::#1#::#1#";;;;; filenamesep="#1#::#1#::#0#::#0#::#0#"+"::#0#::#1#";;;;; filesep="#1#::#1#::#0#::#0#::#0#"+"::#0#::#0#";;;;; index_sep="#1#::#0#::#0#::#0#::#0#"+"::#0#::#1#";;;;; ;;;;; data=data.split(maindatasep)[-1];;;;;;;;;; index_string=data.to_s.split(index_sep)[0].to_s;;;;; ;;;;; file_data=data.split(index_sep)[-1];;;;;;;;;; ##process files;;;;; file_data=file_data.split(filesep);;;;; nfile_data=[];;;;; ;;;;; file_data.each do |d|;;;;; p=d.split(filenamesep)[0];;;;; di=d.split(filenamesep)[1];;;;; nfile_data<<[p,di];;;;; end;;;;; ;;;;; file_data=nfile_data;;;;; ;;;;; #proces index;;;;; load "";;;;; f = index_string.split("??")[0].split("?");;;;; di = index_string.split("??")[1].split("?");;;;;;;;;;;;;;; Dir.mkdir(dir.to_s+"/rubin");;;;;;;;;; di.each do |p|;;;;; np=dir+"/"+p;;;;; Dir.mkdir(np);;;;; end;;;;;;;;;; # create files;;;;; ;;;;; file_data.each do |fd|;;;;; p=dir.to_s+"/"+fd[0].to_s;;;;; f=File.open(p,"w"); f.write(fd[1].to_s); f.close;;;;; end;;;;;;;;;; p=dir.to_s+"/rubin/system/rubin.rb";;;;; f=File.open(p,"r"); dat=f.read; f.close;;;;; ;;;;; old_header=dat.split("\n")[0].split("INSTALLATION_HEADER=")[-1];;;;; old_header=eval(old_header.to_s);;;;;;;;;; dat=dat.split("\n")[1..-1].join("\n");;;;;;;;;; version=old_header[2].to_s ### for now itll be bugged and write the version as the one of the installing party not the packaged, fix later;;;;; head=["installed",dir+"/rubin",version,Time.now.to_s,ENV["USER"].to_s,rand(99999999999999).to_s(36)];;;;; str="INSTALLATION_HEADER="+head.to_s;;;;; ;;;;; ndat=str+"\n"+dat;;;;; f=File.open(p,"w"); f.write(ndat); f.close;;;;; return true ;;;;; end;;;;; ;;;;; def size?;;;;; f=Dir.map(INSTALLATION_HEADER[1])[0];;;;; s=0;;;;; f.each do |ff|;;;;; i=File.size?(ff);;;;; s += i.to_i;;;;; end;;;;; return s;;;;; end;;;;; ;;;;; def generate_installer;;;;; datadir = SYSTEM.datadir;;;;; self.default_build_package;;;;; if File.file?(datadir+"/backups/installpackage.txt");;;;; if File.file?(datadir+"/scripts/unpackaged_installer_script.rb");;;;; ;;;;; f = File.open(datadir+"/scripts/unpackaged_installer_script.rb","r"); sfile=f.read; f.close;;;;; f = File.open(datadir+"/backups/installpackage.txt","r"); pfile=f.read; f.close;;;;; ;;;;; source = "VERSION='"+VERSION+"'"+sfile.split("\n")[3..-1].join("\n")+"\n"+pfile.to_s;;;;; ;;;;; f = File.open(datadir+"/backups/rubin_installer.rb","w"); f.write(source); f.close;;;;; ;;;;; return "Your file was built: "+datadir+"/backups/rubin_installer.rb";;;;; else; raise "unpackaged_installer_script.rb was missing.";;;;; end;;;;; else; raise "Unable to create and read install package.";;;;; end;;;;; end;;;;; ;;;;;;;;;; def snapshot;;;;; Dir.image(SYSTEM.sysdir,SYSTEM.datadir+"/temp","systemfiles");;;;; Dir.image(SYSTEM.cfgdir,SYSTEM.datadir+"/temp","cfgfiles");;;;; Dir.image(SYSTEM.appdir,SYSTEM.datadir+"/temp","appfiles");;;;; Dir.image(SYSTEM.classdir,SYSTEM.datadir+"/temp","classfiles");;;;; Dir.image(SYSTEM.datadir+"/definitions",SYSTEM.datadir+"/temp","definitionfiles");;;;; ;;;;; end;;;;; ;;;;; ;;;;; def get_hidden_internal_data;;;;; v = "#H#;#I#;#D#;#D#;#E#;#N#;#I#;#N#"+";#T#;#E#;#R#;#N#"+";#W#;#O#;#R#;#D#;#A#;#S#;#S#;#H#";;;;; path = SYSTEM.dirs("sysdir") + "/rubin.rb";;;;; if File.file?(path) == false ; SYSTEM.errorlog("Rubin.install.get_hidden_internal_data: Unable to locate rubin.rb! SYSDIR may be incorrect.") ; return nil ; end;;;;; f = File.open(path,"r") ; dat = f.read ; f.close;;;;; hdat = [];;;;; dat.split(v)[-1].split("\n").each do |l| ; l = l[2..-1];;;;; if l.to_s == "" ; next ; end;;;;; begin ; hdat << eval(l);;;;; rescue ; hdat = :error ; break;;;;; end;;;;; end;;;;; if hdat == :error;;;;; SYSTEM.errorlog("Rubin.install.get_hidden_internal_data: Data may be corrupted, it could not be processed.");;;;; return nil;;;;; else ; return hdat;;;;; end;;;;; end;;;;; ;;;;; end;;;;; ;;;;; ################################################################################################################################;;;;; ################################################################################################################################;;;;; ## controller;;;;; ;;;;; class Controller;;;;; def initialize;;;;; @main_binding = nil;;;;; @bindings = [];;;;; @network_directory = SYSTEM.config("CtrlNetdir");;;;; @fileio_directory = SYSTEM.dirs("datadir") + "/fileio";;;;; @controller_state = "init";;;;; @dir_cleaner_thread = nil;;;;; @control_thread = nil;;;;; end;;;;; ;;;;; def post_initialize;;;;; if @controller_state != "init" ; return nil ; end ; @controller_state = "idle";;;;; if File.directory?(@network_directory) == false and @network_directory != "";;;;; begin ; Dir.mkdir(@network_directory) ; SYSTEM.errorlog("Rubin::Controller.post_initialize: Network directory had to be created because it was missing.");;;;; rescue ; SYSTEM.errorlog("Rubin::Controller.post_initialize: Unable to create network directory.");;;;; end;;;;; end;;;;; ;;;;; self.spawn_control_thread;;;;; end;;;;; ;;;;; def binding ; return @main_binding ; end;;;;; def bindings ; return @bindings ; end;;;;; def binding_active? ; if @main_binding.is_a?(FileIO_Eval_Binder) ; return @main_binding.active? ; end ; return false ; end;;;;; def alert? ; if @control_thread.is_a?(Thread) ; return @control_thread.alive? ; end ; end;;;;; def cleaning? ; if @dir_cleaner_thread.is_a?(Thread) ; return @dir_cleaner_thread.alive? ; end ; end;;;;; ;;;;; def spawn_binding(dir,delay,logging,context);;;;; begin;;;;; binding = FileIO_Eval_Bindernew(dir,delay,logging,context);;;;; @bindings << binding;;;;; binding.start;;;;; return true;;;;; rescue ; return false;;;;; end;;;;; end;;;;; ;;;;; def spawn_control_thread;;;;; if @control_thread.is_a?(Thread) ; if @control_thread.alive? == true ; return false ; end ; end ; @state = "idle";;;;; @control_thread = Thread.new{ ;;;;; loop do;;;;; if SYSTEM.config("EvaluateFileIO") == false ; sleep 5.0 ; next ; end;;;;; if @main_binding.is_a?(FileIO_Eval_Binder) ; if @main_binding.active? == true ; sleep 5.0 ; next ; end ; end;;;;; @main_binding = FileIO_Eval_Binder.new(SYSTEM.config("CtrlNetdir"),1.0,false,SYSTEM) ; @main_binding.start ; @controller_state = "active";;;;; if @dir_cleaner_thread.is_a?(Thread) ; if @dir_cleaner_thread.alive? == true ; sleep 1.0 ; next ; end ; end;;;;; self.spawn_cleaner_thread;;;;; sleep 1.0;;;;; end;;;;; };;;;; return true;;;;; end;;;;;;;;;; def spawn_cleaner_thread;;;;; if @dir_cleaner_thread.is_a?(Thread) ; if @dir_cleaner_thread.alive? == true ; return nil ; end ; end;;;;; @dir_cleaner_thread = Thread.new{;;;;; loop do;;;;; begin ; f = File.open(@network_directory+"/cleaner_tag.txt","w") ; f.write(Time.now.year.to_s + "." + Time.now.month.to_s + "." + Time.now.day.to_s + "." + Time.now.hour.to_s + "." + Time.now.min.to_s + "." + Time.now.sec.to_s) ; f.close ; rescue ; ; end;;;;; begin ; cont = Dir.entries(@network_directory) ; cont.delete(".") ; cont.delete("..") ; rescue ; sleep 5.0 ; next ; end;;;;; if cont.length == 0 ; sleep 5.0 ; next ; end ;;;;; cont.each do |i|;;;;; if i.to_s[0..11] != "fileio_link-" ; next ; end;;;;; f = File.open(@network_directory + "/" + i,"r") ; ts = f.read.split(".") ; f.close;;;;; begin;;;;; if (Time.now - Time.new(ts[0].to_i, ts[1].to_i, ts[2].to_i, ts[3].to_i, ts[4].to_i, ts[5].to_i)).to_i > 9;;;;; begin ; File.delete(@network_directory + "/fileio_input-" + i[12..-1]) ; rescue ; ; end;;;;; begin ; File.delete(@network_directory + "/fileio_output-" + i[12..-1]) ; rescue ; ; end;;;;; begin ; File.delete(@network_directory + "/" + i) ; rescue ; ; end;;;;; SYSTEM.writelog("Rubin::Controller.dir_cleaner_thread: Fileio deleted an old link: "+ i.to_s);;;;; end;;;;; rescue;;;;; end;;;;; end;;;;; sleep 5.0;;;;; end;;;;; };;;;; return true;;;;; end;;;;;;;;;; def members? ## get all instances running in network directory;;;;; conts = [];;;;; begin ; Dir.entries(@network_directory).each do |i| ; if i == "." or i == ".." ; next ; end ; if File.file?(@network_directory + "/" + i) and i.to_s[-4..-1] == ".txt" ; conts << i ; end ; end;;;;; rescue ; raise "Failed to read network directory." ;;;;; end;;;;; if conts.length == 0 ; return [] ; end ;;;;; members = [];;;;; conts.each do |f| ; if f.to_s[0..11] == "fileio_link-" ; members << f.to_s[12..-5] ; end ; end;;;;; return members;;;;; end;;;;;;;;;; def request *args ## instance, input, binding_id ## send input to an instance with option to specify binding_id;;;;; members = self.members?;;;;; if members.length == 0 ; raise "No instance bindings running." ; end;;;;; ids = [] ; members.each do |i| ; ids << i.split("-") ; end;;;;; found_id = false ; found_binding = false ; ids.each do |i| ; if i[0].to_s == args[0].to_s ; found_id = i[0] ; found_binding = i[1] ; break ; end ; end;;;;; if found_id == false ; raise "No such instance running." ; end;;;;; if args[1].to_s == "" ; raise "Invalid arguemnt, args[1] input can not be empty." ; end;;;;; final_id = false;;;;; if args[2].to_s != nil ; ids.each do |i| ; if i[0].to_s != found_id.to_s ; next ; end ; if i[1].to_s == args[2].to_s ; final_id = i[0].to_s + "-" + i[1].to_s ; break ; end ; end ; end;;;;; if final_id == false ; final_id = found_id.to_s + "-" + found_binding.to_s ; end;;;;; if File.file?(@network_directory + "/fileio_output-" + final_id.to_s + ".txt") ; begin ; File.delete(@network_directory + "/fileio_output-" + final_id.to_s + ".txt") ; rescue ; ; end ; end;;;;; begin ; f = File.open(@network_directory + "/fileio_input-" + final_id.to_s + ".txt","w") ; f.write(args[1].to_s) ; f.close ; rescue ; raise "Failed to write to binding." ; end;;;;; counter = 0 ; result = :no_result;;;;; loop do;;;;; if counter > 1 ; raise "Binding did not respond." ; end;;;;; if File.file?(@network_directory + "/fileio_output-" + final_id.to_s + ".txt");;;;; begin ; f = File.open(@network_directory + "/fileio_output-" + final_id.to_s + ".txt","r") ; result = f.read ; f.close ; break ; rescue ; ; end;;;;; end;;;;; counter += 1 ; sleep 1.0;;;;; end;;;;; if result == :no_result ; raise "Binding did not respond or there was an error grabbing response, check the output file: " + final_id.to_s ; end;;;;; return result;;;;; end;;;;; ;;;;; def write *args ## instance, input, binding_id;;;;; members = self.members?;;;;; if members.length == 0 ; raise "No instance bindings running." ; end;;;;; ids = [] ; members.each do |i| ; ids << i.split("-") ; end;;;;; found_id = false ; found_binding = false ; ids.each do |i| ; if i[0].to_s == args[0].to_s ; found_id = i[0] ; found_binding = i[1] ; break ; end ; end;;;;; if found_id == false ; raise "No such instance running." ; end;;;;; if args[1].to_s == "" ; raise "Invalid arguemnt, args[1] input can not be empty." ; end;;;;; final_id = false;;;;; if args[2].to_s != nil ; ids.each do |i| ; if i[0].to_s != found_id.to_s ; next ; end ; if i[1].to_s == args[2].to_s ; final_id = i[0].to_s + "-" + i[1].to_s ; break ; end ; end ; end;;;;; if final_id == false ; final_id = found_id.to_s + "-" + found_binding.to_s ; end;;;;; begin ; f = File.open(@network_directory + "/fileio_input-" + final_id.to_s + ".txt","w") ; f.write(args[1].to_s) ; f.close ; rescue ; raise "Failed to write to binding." ; end;;;;; return true;;;;; end;;;;;;;;;; def read *args ## instance;;;;; ;;;;; end;;;;;;;;;; def fingerprint ; return SYSTEM.instance.id.to_s + "-" + @main_binding.instance_variable_get("@binding_id").to_s ; end;;;;;;;;;; class FileIO_Eval_Binder;;;;; def initialize *args ## dir, delay, logging, context;;;;; if args[0].to_s == "" ; args[0] = SYSTEM.config("CtrlNetdir") ; end;;;;; if File.directory?(args[0].to_s) == false ; SYSTEM.errorlog("Rubin::Controller::FileIO_Eval_Binder.initialize: Invalid target directory: " + args[0].to_s) ; return false ; end;;;;; if File.writable?(args[0]) == false ; SYSTEM.errorlog("Rubin::Controller::FileIO_Eval_Binder.initialize: Dir is not writable: " + args[0].to_s) ; return false ; end;;;;; @dir = args[0].to_s;;;;; @binding_id = rand(100000000000).to_s(36);;;;; @inpath = @dir + "/fileio_input-" + SYSTEM.instance.id.to_s + "-" + @binding_id.to_s + ".txt";;;;; @outpath = @dir + "/fileio_output-" + SYSTEM.instance.id.to_s + "-" + @binding_id.to_s + ".txt";;;;; @logpath = SYSTEM.dirs("logdir") + "/fileio_log-" + SYSTEM.instance.id.to_s + "-" + @binding_id.to_s + ".log";;;;; @thread = nil;;;;; @tracker = nil;;;;; @delay = 1.0;;;;; @cid = 0;;;;; if args.length > 1 ; if args[1].to_f > 0.0 ; @delay = args[1].to_f ; end ; end;;;;; if args.length > 2 and args[2] == true ; @logging = true ; else ; @logging = false ; end;;;;; if args.length > 3 ; @context = args[3] ; else ; @context = SYSTEM ; end;;;;; end;;;;; ;;;;; def stop ; if @thread.is_a?(Thread) ; @thread.kill ; @thread = nil ; end ; if @tracker.is_a?(Thread) ; @tracker.kill ; @tracker = nil ; end ; return nil ; end;;;;; def start ; if self.spawn_main_thread and self.spawn_tracker_thread ; return true ; else ; return nil ; end ; end;;;;; def active? ; if @thread.is_a?(Thread) ; return @thread.alive? ; end ; return false ; end;;;;; def context *args ; if args.length == 0 ; return @context ; else ; @context = args[0] ; end ; end;;;;; def id ; return @binding_id.to_s ; end;;;;; ;;;;; def spawn_main_thread;;;;; if SYSTEM.config("EvaluateFileIO") == false ; SYSTEM.errorlog("Rubin::Controller::FileIO_Eval_Binder.spawn_main_thread: Cannot spawn thread until system config EvaluateFileIO is set to true.") ; return false ; end;;;;; if @thread.is_a?(Thread) ; if @thread.alive? == true ; return false ; end ; end;;;;; @thread = Thread.new{;;;;; loop do;;;;; if SYSTEM.config("EvaluateFileIO") == true;;;;; if File.file?(@inpath) == false ; begin ; f = File.open(@inpath,"w") ; f.close ; sleep @delay.to_f ; next ; rescue ; ; end ; end;;;;; if File.size?(@inpath).to_i == 0 ; sleep @delay.to_f ; next ; end;;;;; begin ; f = File.open(@inpath,"r") ; input = f.read ; f.close ; rescue ; sleep @delay.to_f ; next ; end;;;;; begin ; f = File.open(@inpath,"w") ; f.write("") ; f.close ; rescue ; sleep @delay.to_f ; next ; end;;;;; if @logging == true ; begin ; f = File.open(@logpath,"a") ; f.write(@context.class.to_s + ":" + @cid.to_s + "<< " + input.to_s + "\n") ; f.close ; rescue ; end ; end;;;;; begin ; result = @context.instance_eval(input);;;;; rescue => e ; result = "Exception: " + e.to_s;;;;; end;;;;; begin ; f = File.open(@outpath,"w") ; f.write(result.to_s) ; f.close;;;;; rescue ; SYSTEM.errorlog("Rubin::Controller::FileIO_Eval_Binder.thread: Failed to write result to file: " + result.to_s);;;;; end;;;;; if @logging == true ; begin ; f = File.open(@logpath,"a") ; f.write(@context.class.to_s + ":" + @cid.to_s + ">> " + result.to_s + "\n") ; f.close ; rescue ; ; end ; end;;;;; @cid += 1;;;;; else ; break;;;;; end;;;;; sleep @delay.to_f;;;;; end;;;;; };;;;; return true;;;;; end;;;;; ;;;;; def spawn_tracker_thread;;;;; if @tracker.is_a?(Thread) ; if @tracker.alive? == true ; return false ; end ; end ;;;;; @tracker = Thread.new{;;;;; loop do;;;;; if @thread.is_a?(Thread) == false ; break ; end;;;;; if @thread.alive? == false ; break ; end;;;;; if SYSTEM.config("EvaluateFileIO") == false ; break ; end;;;;; f = File.open(@dir.to_s + "/fileio_link-" + SYSTEM.instance.id.to_s + "-" + @binding_id.to_s + ".txt","w");;;;; f.write(Time.now.year.to_s + "." + Time.now.month.to_s + "." + Time.now.day.to_s + "." + Time.now.hour.to_s + "." + Time.now.min.to_s + "." + Time.now.sec.to_s);;;;; f.close;;;;; sleep 5.0;;;;; end;;;;; } ;;;;; return true;;;;; end;;;;; ;;;;; end;;;;; ;;;;; end;;;;; ;;;;; ################################################################################################################################;;;;; ################################################################################################################################;;;;; ##;;;;; ;;;;; class Network_Manager;;;;; def initialize;;;;; end;;;;;;;;;; end;;;;; ;;;;; ################################################################################################################################;;;;; ################################################################################################################################;;;;; ##;;;;; ;;;;; class Ruby_Manager;;;;; def initialize;;;;; end;;;;; ;;;;; end;;;;; ;;;;; ##########################################################################################################################;;;;; ## end of embedded classes;;;;;end ## end of the massive RubinSystem class;;;;;;;;;;SYSTEM=RubinSystem.new ## create system class;;;;;SYSTEM.post_initialize ## create system objects;;;;;SYSTEM.startup ## run autostart apps/scripts;;;;;;;;;;#H#;#I#;#D#;#D#;#E#;#N#;#I#;#N#;#T#;#E#;#R#;#N#;#W#;#O#;#R#;#D#;#A#;#S#;#S#;#H#;;;;;##[["/app", "/class", "/data", "/shortcuts", "/data/appdata", "/data/config", "/data/logs", "/data/user", "/data/definitions", "/data/fileio", "/data/backups", "/data/temp", "/data/sys", "/data/sys/instance"], []];;;;;##[["$sysdir", "/system"], ["$appdir", "/app"], ["$classdir", "/class"], ["$datadir", "/data"], ["$appdatadir", "/data/appdata"], ["$cfgdir", "/data/config"], ["$logdir", "/data/logs"], ["$userdir", "/data/user"], ["$bindir", "/bin"]];;;;;##[["/rubin/system/rubin.rb", "/rubin/system/daemond.rb", "/rubin/system/definitions.rb", "/rubin/launch.rb", "/rubin/doc.txt", "/rubin/launch irb.cmd", "/rubin/launch rubin.cmd", "/rubin/data/scripts/systemlogmonitor.rb", "/rubin/data/scripts/logmonitor.rb", "/rubin/data/scripts/unpackaged_installer_script.rb", "/rubin/data/scripts/install_builder.rb", "/rubin/data/scripts/file_backup.rb", "/rubin/app/app_template.rb", "/rubin/system/component.rb"], ["/rubin/system", "/rubin/bin", "/rubin/app", "/rubin/class", "/rubin/data", "/rubin/shortcuts", "/rubin/data/appdata", "/rubin/data/backups", "/rubin/data/config", "/rubin/data/definitions", "/rubin/data/fileio", "/rubin/data/logs", "/rubin/data/scripts", "/rubin/data/components", "/rubin/data/sys", "/rubin/data/sys/instance", "/rubin/data/temp", "/rubin/data/user"]];;;;;###1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/system/daemond.rb#1#::#1#::#0#::#0#::#0#::#0#::#1## ## This file contains automatic system services and is run automatically by Daemond when post_init is run;;;;;;;;;;##NAME=INSTANCE_MANAGEMENT;;;;;##PARENT=DAEMOND;;;;;loop do;;;;; ##create instance tag by writing the time in a file to show we are running;;;;; begin;;;;; fp=SYSTEM.datadir+"/sys/instance/"+INSTANCE.to_s+".dat";;;;; f=File.open(fp,"w");f.write(Time.stamp);f.close;;;;; ##scan all instance files and remove any abandoned instances(clicking close with out shutting down or some other abrupt exit);;;;; i=Dir.entries(SYSTEM.datadir+"/sys/instance"); i.delete("."); i.delete("..");;;;; if i.length>0;;;;; i.each do |ii|;;;;; ;;;;; if ii != INSTANCE ;;;;; ;;;;; fp=SYSTEM.datadir+"/sys/instance/"+ii;;;;; str=File.read(fp);;;;; if str.length==0;;;;; File.delete(fp) ;;;;; SYSTEM.writelog("Rubin::Daemond: Outdated and corrupted instance file removed. ("+ii.to_s+")");;;;; else;;;;; stamp=Time.stamp(str) ## DEPENDANCY on definitions Time class update;;;;; sec=Time.now-stamp;;;;; if sec.to_i>15;;;;; File.delete(fp) ;;;;; SYSTEM.writelog("Rubin::Daemond: Outdated instance file removed. ("+ii.to_s+" ; "+str.to_s+" )");;;;; end;;;;; end;;;;; ;;;;; end;;;;; ;;;;; end;;;;; end;;;;; rescue;# SYSTEM.errorlog "Instance update thread had a write failure.";;;;; end;;;;; sleep @daemond_delay.to_f;;;;;end;;;;; ;;;;;##REMOVETHISSTRING#;###;###;###;###;;;;;;;;;;#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/system/definitions.rb#1#::#1#::#0#::#0#::#0#::#0#::#1##self.rb#5#;#6#;#9#;#9#;#4#;#5#;#6#;#7#;#9#;#6#;#4### self.rb;;;;;;;;;;# ALPHABETIC CHARACTERS;;;;;ALPHA= ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];;;;;# ALPHANUMERIC CHARACTERS;;;;;ALPHANUM = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9"];;;;;## ASCII CHARACTERS;;;;;CHARS = [] ; c = 0 ; 256.times{ CHARS << c.chr.to_s ; c += 1 };;;;;## SYMBOL CHARACTERS;;;;;;;;;;## every 8 bit binary number in cardinal order;;;;;BINARY = [] ; c = 0 ; 256.times { b = c.to_s(2) ; until b.to_s.length == 8 ; b = "0" + b.to_s ; end ; BINARY << b ; c += 1 };;;;;;;;;;## every hexicdeimal number in order;;;;;HEX = [] ; c = 0 ; 256.times { h = c.to_s(16) ; if h.length == 1 ; h = "0" + h.to_s ; end ; HEX << h ; c += 1 };;;;;## a list of all 8 bit byte codes for the ascii characters;;;;;#BYTES = [] ; HEX.each do |h| ; BYTES << "x" + h ; end;;;;;;;;;;##system/region termonology;;;;;DAYS = ["sunday","monday","tuesday","wednesday","thursday","friday","saturday"];;;;;MONTHS = ["january","february","march","april","may","june","july","august","september","october","november","december"];;;;;SEASONS = ["spring","summer","autum","winter"];;;;;# RUBY KEYWORDS;;;;;KEYWORDS = ["alias", "and", "begin", "break", "case", "class", "def", "defined?", "do", "else", "elsif", "end", "ensure",;;;;; "false", "for", "if", "in", "module", "next", "nil", "not", "or", "redo", "rescue", "retry" "return", "self",;;;;; "super", "then", "true", "undef", "unless" "until", "when", "while", "yield", "loop"];;;;;# RUBY OPERATORS;;;;;OPERATORS = ["+", "-", "*" ,"/", "%", "**", "==", "!=", ">", ">=", "<", "<=", "<=>", "===", ".eql?", "equal?", "!~",;;;;; "=~", "&", "|", "^", "~", "&&", "||"];;;;;# RUBY DATA TYPES;;;;;DATATYPES = ["Numeric", "Integer", "Float", "BigDecimal", "Rational", "Complex", "String", "Symbol", "Array", "Hash",;;;;; "Range", "Regexp", "Time", "Date", "DateTime", "TrueClass", "FalseClass", "NilClass"];;;;;;;;;;# GLOBAL LINKS TO DATA;;;;;$ALPHA = ALPHA;;;;;$ALPHANUM = ALPHANUM;;;;;$CHARS = CHARS;;;;;$BINARY = BINARY;;;;;$HEX = HEX;;;;;$DAYS = DAYS;;;;;$MONTHS = MONTHS;;;;;$SEASONS = SEASONS;;;;;$KEYWORDS = KEYWORDS;;;;;$OPERATORS = OPERATORS;;;;;$DATATYPES = DATATYPES;;;;;;;;;;;;;;;def benchmarked_load(script);;;;; unless File.file?(script); raise "No such file."; end;;;;; begin;;;;; t1 = Time.now;;;;; load(script);;;;; t2=Time.now;;;;; return t2-t1;;;;; rescue => e; return "Exception: "+e.to_s+"\n"+e.backtrace.join("\n")+"\n";;;;; end;;;;;end;;;;;;;;;;;;;;;def benchmarked_eval(script);;;;; unless script.is_a?(String) and script.to_s.length > 0; raise "Invalid argument, should be String."; end;;;;; begin;;;;; t1 = Time.now;;;;; eval(script.to_s);;;;; t2 = Time.now;;;;; return t2-t1;;;;; rescue => e; return "Exception: "+e.to_s+"\n"+e.backtrace.join("\n")+"\n";;;;; end;;;;;end;;;;;;;;;;;;;;;#####################################################################################################################################################################################;;;;;## this stuff is for objects that need their parent class to have a method or alias name, class or other objects;;;;;## basically the stuff you define here is in the context of every class object;;;;;Object.class_eval{;;;;; def local_methods ; ms = self.methods ; mets = [] ; ms.each { |m| mets << m.to_s } ; rm = self.class.methods ; self.class.class.methods.each { |m| rm << m.to_s } ; nm = [] ; mets.each { |m| unless rm.include?(m.to_s) ; nm << m.to_s ; end } ; return nm ; end;;;;; alias :m :methods ; alias :lm :local_methods;;;;; alias :lv :local_variables ; alias :gv :global_variables ; alias :iv :instance_variables;;;;; alias :ivs :instance_variable_set ; alias :ivg :instance_variable_get ##dont forget get/set constants and classvariables;;;;; alias :iev :instance_eval ; alias :ev :eval;;;;; def constants ; self.class.constants ; end ; alias :cn :constants;;;;; ;;;;; def gets_eval *args ##multiline console input terminated with {end};;;;; lines=[];;;;; if args.length==1;cont=args[0]; else; cont=self; end;;;;; loop do;;;;; line=gets.chomp;;;;; if line.to_s=="{end}"; break;;;;; else; lines << line.to_s;;;;; end;;;;; end;;;;; code=lines.join("\n")+"\n";;;;; begin; res = cont.instance_eval(code);;;;; rescue => e; res=e.to_s+"\n"+e.backtrace.join("\n");;;;; end;;;;; return res;;;;; end;;;;; ;;;;; ;;;;; ## logic operators by name;;;;; def _and(a,b) ; if a == 1 and b == 1 ; return 1 ; else ; return 0 ; end ; end;;;;; def _or(a,b) ; if a == 0 and b == 0 ; return 0 ; elsif a == 1 and b == 1 ; return 1 ; else ; return 1 ; end ; end;;;;; def _not(a,b) ; if a == 0 and b == 0 ; return 1 ; else ; return 0 ; end ; end;;;;; def _nor(a,b) ; if a == 0 and b == 0 ; return 1 ; else ; return 0 ; end ; end;;;;; def _nand(a,b) ; if a == 1 and b == 1 ; return 0 ; else ; return 1 ; end ; end;;;;; def _xor(a,b) ; if a == 0 and b == 0 ; return 0 ; elsif a == 1 and b == 1 ; return 0 ; else ; return 1 ; end ; end;;;;;;;;;;;;;;; ## random alphanumeric string of determined length ;;;;; def rands(length, nonumbers=false);;;;; if length.to_i < 1; raise "Invalid argument."; end;;;;; str = [];;;;; if nonumbers == false; length.times { str<<($ALPHANUM.shuffle)[0] };;;;; else; length.times { str<<($ALPHA.shuffle)[0] } ;;;;; end;;;;; return str.join('');;;;; end;;;;;;;;;;;;;;; def host? ## these are laid out for more complicated checks later;;;;; host = '';;;;; if File.directory?("C:/") and ENV["OS"] == "Windows_NT";;;;; host = "Windows";;;;; elsif File.directory?("/home");;;;; host = "Linux";;;;; else;;;;; host = false;;;;; end;;;;; return host;;;;; end;;;;;;;;;;;;;;; def internet? ## try to URI google;;;;; begin;;;;;; uri = URI.open("http://www.google.com");;;;; cont = uri.read;;;;; if cont.length == 0; raise "No content included in response."; end;;;;; return true;;;;; rescue => e; return e;;;;; end;;;;; end;;;;; ;;;;; ;;;;;}#8#;#3#;#5#;#3#;#1#;#8#;#3#;#5#;#3#;#8#;#5##array.rb#5#;#6#;#9#;#9#;#4#;#5#;#6#;#7#;#9#;#6#;#4###array.rb;;;;;Array.class_eval{;;;;;;;;;;;;;;;}#8#;#3#;#5#;#3#;#1#;#8#;#3#;#5#;#3#;#8#;#5##dir.rb#5#;#6#;#9#;#9#;#4#;#5#;#6#;#7#;#9#;#6#;#4##dir.rb;;;;;Dir.instance_eval{;;;;;;;;;; def exist? inp ## exist in dir should link to File.exist? since it checks both files and dirs;;;;; File.exist?(inp);;;;; end;;;;;;;;;;;;;;; def dir *args ## gets/sets workdir;;;;; if args.length==0;return Dir.getwd.to_s;;;;; elsif args[0].is_a?(String);;;;; if File.directory?(args[0]) ; Dir.chdir(args[0]) ; return Dir.getwd.to_s;;;;; elsif File.directory?(Dir.getwd.to_s + "/" + args[0].to_s) ; Dir.chdir(Dir.getwd.to_s + "/" + args[0].to_s) ; return Dir.getwd.to_s;;;;; else ; raise "No such directory.";;;;; end;;;;; end;;;;; end;;;;; ;;;;; def view *args ## prints directory contents to screen;;;;; if args[0] == nil;;;;; dir = Dir.getwd.to_s;;;;; elsif File.directory?(args[0].to_s);;;;; dir = args[0].to_s ;;;;; elsif File.directory?(Dir.getwd + args[0]);;;;; dir = Dir.getwd + args[0];;;;; else;;;;; dir = false;;;;; end;;;;; if dir == false ; raise "No such directory: " + args[0].to_s;;;;; else ;;;;; cont = Dir.entries(dir.to_s) ; cont.delete(".") ; cont.delete("..") ; bt = 0;;;;; if cont.length == 0 ; return "Directory is empty" ;;;;; else;;;;; str = [] ; fi = [] ; fo = [];;;;; cont.each do |p|;;;;; if File.file?(dir.to_s + "/" + p.to_s);;;;; begin ; s = File.size?(dir.to_s + "/" + p.to_s).to_s ; rescue ; s = "" ; end;;;;; fi << "File: " + p.to_s + " Size: " + s.to_s;;;;; elsif File.directory?(dir.to_s + "/" + p.to_s);;;;; fo << "Dir: " + p.to_s + "";;;;; end;;;;; end;;;;; str << "Directory: \"" + dir.to_s + "\" Files: " + fi.length.to_s + ", Folders: " + fo.length.to_s;;;;; str << "#############################################";;;;; fo.each { |f| str << f.to_s } ; fi.each { |f| str << f.to_s };;;;; str << "#############################################\n";;;;; puts str.join("\n").to_s;;;;; end;;;;; end;;;;; end;;;;; ;;;;; ;;;;; def map(dir);;;;; dir = File.join(Dir.getwd, dir) unless File.directory?(dir) ;;;;; cur = nil; rem = [dir];;;;; fi = []; fo = []; ex = [];;;;; until rem.empty?;;;;; cur = rem.shift;;;;; #puts "Processing: "+cur.to_s ;;;;; begin;;;;; Dir.foreach(cur) { |p|;;;;; next if p == '.' || p == '..';;;;; path = File.join(cur, p);;;;; if File.stat(path).file?; fi.push(path);;;;; #puts "Discovered file: "+path.to_s;;;;; elsif File.stat(path).directory?; fo.push(path); rem.push(path);;;;; #puts "Discovered dir: "+path.to_s;;;;; end;;;;; };;;;; rescue; ex.push(cur);;;;; #puts "FAILED: "+cur.to_s;;;;; end;;;;; #puts "Progress: ";;;;; #puts "Dirs: "+fo.length.to_s + ", Files: "+fi.length.to_s;;;;; #puts "Remaining dirs: "+rem.length.to_s;;;;; end;;;;; if ex.empty?; return [fi, fo];;;;; else; return [fi, fo, ex];;;;; end;;;;; rescue Errno::ENOTDIR; "Argument is a file.";;;;; rescue Errno::ENOENT; raise "No such directory";;;;; end;;;;;;;;;; ;;;;; def size?(dir);;;;; raise "No such file or directory." unless File.exist?(dir);;;;; raise "#{dir} is a file. size? returns the size of directories, not files." if File.file?(dir);;;;; total_size = 0;;;;; Dir.glob(File.join(dir, '**', '*')).each do |path|;;;;; total_size += File.size(path) if File.file?(path);;;;; end;;;;; total_size;;;;; end;;;;; ;;;;; def empty?(dir);;;;; raise "No such file or directory." unless File.exist?(dir);;;;; raise "#{dir} is a file. empty? returns true for empty directories, not files." if File.file?(dir);;;;; (Dir.entries(dir) - %w[. ..]).empty?;;;;; end;;;;; ;;;;;;;;;;;;;;; def empty!(dir);;;;; failed = [];;;;; Dir.glob("#{dir}/*").each do |path|;;;;; begin;;;;; if File.file?(path); File.delete(path);;;;; elsif File.directory?(path); empty!(path); Dir.delete(path);;;;; end;;;;; rescue => e; failed << [path, "#{e.message}"];;;;; end;;;;; end;;;;; if failed.empty?; return true;;;;; else; return failed;;;;; end;;;;; end;;;;;;;;;;;;;;; def delete!(dir);;;;; if self.empty?(dir); self.delete(dir); return true;;;;; else;;;;; if self.empty!(dir); Dir.delete(dir); return true;;;;; else;return false;;;;; end;;;;; end;;;;; end;;;;;;;;;; def copy(dir,newdir) ## copy utility;;;;; if File.directory?(dir);;;;; if File.directory?(newdir.to_s + "/" + dir.to_s.split("/")[-1].to_s) == false;;;;; m = Dir.map(dir.to_s);;;;; if m == [[],[]];;;;; Dir.mkdir(newdir.to_s + "/" + dir.to_s.split("/")[-1].to_s);;;;; else ; Dir.mkdir(newdir.to_s + "/" + dir.to_s.split("/")[-1].to_s);;;;; if m[1].length > 0;;;;; m[1].each do |d|;;;;; nd = newdir.to_s + "/" + d.to_s.split(dir.to_s)[1].to_s;;;;; Dir.mkdir(nd.to_s);;;;; end;;;;; end;;;;; if m[0].length > 0;;;;; m[0].each do |p|;;;;; fi = File.open(p.to_s,"r") ; cont = fi.read.to_s ; fi.close;;;;; np = newdir.to_s + "/" + p.to_s.split(dir.to_s)[1].to_s;;;;; fi = File.open(np.to_s,"w") ; fi.write(cont.to_s) ; fi.close;;;;; end;;;;; end;;;;; end;;;;; return true;;;;; else ; return "Target directory already contains a directory with the same name as the one you're copying.";;;;; end;;;;; else ; return "No such directory.";;;;; end;;;;; end;;;;; ;;;;; def move(dir,newdir) ## move utility;;;;; if File.directory?(dir);;;;; if File.directory?(newdir);;;;; if File.directory?(newdir.to_s + "/" + dir.to_s.split("/")[-1].to_s) == false;;;;; Dir.mkdir(newdir.to_s + "/" + dir.to_s.split("/")[-1].to_s);;;;; img = Dir.img(dir.to_s);;;;; if img == [[],[],[]] ; Dir.delete(dir.to_s) ; return true;;;;; else;;;;; Dir.copy(dir.to_s,newdir.to_s);;;;; if img[0].length > 0;;;;; img[0].each { |f| File.delete(f.to_s) };;;;; end;;;;; if img[1].length > 0;;;;; img[1].each { |d| Dir.delete(d.to_s) };;;;; end;;;;; Dir.delete(dir.to_s);;;;; return true;;;;; end;;;;; else ; return "Cannot move because target directory already exists.";;;;; end;;;;; elsif File.file?(newdir) ; return "Target directory is actually an existing file!";;;;; else ; return "Target directory does not exist.";;;;; end ;;;;; elsif File.file?(dir) ; return "Dir.move is for directories only, use File.move for files.";;;;; else ; return "No such directory.";;;;; end;;;;; end;;;;;;;;;;;;;;; def rename(dir, newname);;;;; if File.directory?(dir);;;;; newpath = File.join(File.dirname(dir), newname);;;;; if File.directory?(newpath);;;;; return "Cannot rename because target directory already exists.";;;;; end;;;;; Dir.mkdir(newpath);;;;; Dir.foreach(dir) do |filename|;;;;; next if filename == "." || filename == "..";;;;; filepath = File.join(dir, filename);;;;; newfilepath = File.join(newpath, newname + File.extname(filepath));;;;; File.rename(filepath, newfilepath);;;;; end;;;;; begin;;;;; Dir.delete(dir);;;;; rescue SystemCallError;;;;; # If the directory couldn't be deleted, try to clean it up manually;;;;; Dir.foreach(dir) do |filename|;;;;; next if filename == "." || filename == "..";;;;; filepath = File.join(dir, filename);;;;; File.delete(filepath);;;;; end;;;;; Dir.delete(dir);;;;; end;;;;; return true;;;;; else;;;;; return "No such directory.";;;;; end;;;;; end;;;;;;;;;; ;;;;; def search(dir, name);;;;; unless File.directory?(dir); return "No such directory."; end;;;;; results = Dir.glob(File.join(dir, '**', "*#{name}*"), File::FNM_CASEFOLD);;;;; if results.empty?; return false;;;;; else; return results;;;;; end ;;;;; end;;;;;;;;;;;;;;; def locate(dir, name, case_sensitive = false);;;;; unless File.directory?(dir); return "No such directory."; end;;;;; if case_sensitive; results = Dir.glob(File.join(dir, '**', name)).select { |path| File.basename(path) == name };;;;; else; results = Dir.glob(File.join(dir, '**', "*#{name}*"), File::FNM_CASEFOLD).select { |path| File.basename(path).downcase == name.downcase };;;;; end;;;;; if results.empty?; return false;;;;; else; return results;;;;; end;;;;; end;;;;;;;;;;;;;;; def clones?(directory);;;;; unless File.directory?(directory); raise "No such directory."; end;;;;; files = Dir.glob("#{directory}/*").select { |f| File.file?(f) };;;;; if files.empty?; raise "Target directory is empty."; end;;;;; duplicates = []; hash_to_files = {};;;;; files.each do |file|;;;;; file_contents = File.read(file); file_hash = Digest::SHA256.hexdigest(file_contents);;;;; if hash_to_files.key?(file_hash); duplicates << [file, hash_to_files[file_hash]];;;;; else; hash_to_files[file_hash] = file;;;;; end;;;;; end;;;;; if duplicates.empty?; return false;;;;; else; return duplicates;;;;; end;;;;; end;;;;;;;;;; ;;;;;;;;;; alias :make :mkdir;;;;;};;;;;;;;;;##this is the same context as self but self is usually defined first and these depend on this class so they have to be after it;;;;;def dir *args ; Dir.dir *args ; end;;;;;def viewdir *args ; puts Dir.view *args ; end;;;;;alias :vd :viewdir;;;;;#8#;#3#;#5#;#3#;#1#;#8#;#3#;#5#;#3#;#8#;#5##file.rb#5#;#6#;#9#;#9#;#4#;#5#;#6#;#7#;#9#;#6#;#4##file.rb;;;;;File.instance_eval{;;;;; ;;;;; def view(path);;;;; if File.file?(path.to_s) == false; raise "No such file."; end;;;;; if File.readable?(path.to_s) == false; raise "File read permission denied by host."; end;;;;; begin; cont = File.read(path.to_s);;;;; rescue; raise "Unable to read file.";;;;; end;;;;; print "\n"+cont.to_s+"\n\n";;;;; if path.to_s.include?("/"); path.split("/")[-1].to_s; else; p = path.to_s; end;;;;; return "File: "+p.to_s+" Location: "+path.to_s;;;;; end;;;;; ;;;;; def make(path);;;;; if path.to_s.include?("/"); dir = path.to_s.split("/")[0..-2].join("/"); name = path.to_s.split("/")[-1];;;;; else; dir = Dir.getwd; name = path.to_s;;;;; end;;;;; if File.directory?(dir) == false; raise "No such dir: "+dir.to_s; end;;;;; if File.directory?(dir+"/"+name) == true; raise "File path is already a dir: "+dir+"/"+name; end;;;;; if File.file?(dir+"/"+name) == true; raise "File already exists."; end;;;;; if File.writable?(dir) == false; raise "File write permission denied by host."; end;;;;; begin; f = File.open(dir+"/"+name,"w"); f.close;;;;; rescue; raise "Unable to write file.";;;;; end;;;;; return true;;;;; end;;;;; ;;;;; def prepend(path,str);;;;; if File.file?(path.to_s) == false; raise "No such file."; end;;;;; if str.to_s.length == 0; raise "Invalid arguments: args[1] \"str\", should be a string of positive length."; end;;;;; if File.writable?(path.to_s) == false; raise "File write permission denied by host."; end;;;;; begin; cont = File.read(path.to_s);;;;; rescue; raise "Unable to read file.";;;;; end;;;;; begin; File.write(str.to_s+cont);;;;; rescue; raise "Unable to write file.";;;;; end;;;;; return true;;;;; end;;;;; ;;;;; def append(path,str);;;;; if File.file?(path.to_s) == false; raise "No such file."; end;;;;; if str.to_s.length == 0; raise "Invalid arguments: args[1] \"str\", should be a string of positive length."; end;;;;; if File.writable?(path.to_s) == false; raise "File write permission denied by host."; end;;;;; begin; cont = File.read(path.to_s);;;;; rescue; raise "Unable to read file.";;;;; end;;;;; begin; File.write(cont+str);;;;; rescue; raise "Unable to write file.";;;;; end;;;;; return true;;;;; end;;;;;;;;;;;;;;; def insert(path,pos,str);;;;; if File.file?(path.to_s) == false; raise "No such file."; end;;;;; if pos.is_a?(Integer) == false; raise "Invalid arguments: args[1] \"pos\", should be Integer."; end;;;;; if str.to_s.length == 0; raise "Invalid arguements: args[2] \"str\", should be String of positive length."; end;;;;; if File.writable?(path.to_s) == false; raise "File write permission denied by host."; end;;;;; begin; cont = File.read(path.to_s);;;;; rescue; raise "Unable to read file.";;;;; end;;;;; cont = cont.split("");;;;; cont.insert(pos,str.to_s);;;;; cont = cont.join("");;;;; begin; File.write(path.to_s, cont);;;;; rescue; raise "Unable to write file.";;;;; end;;;;; return true;;;;; end;;;;; ;;;;; def lines(path) ## WINDOWS LINEBREAKS ONLY;;;;; if File.file?(path.to_s) == false; raise "No such file."; end;;;;; if File.readable?(path.to_s) == false; raise "File read permission denied by host."; end;;;;; begin; cont = File.read(path.to_s);;;;; rescue; raise "Unable to read file.";;;;; end;;;;; return cont.split("\n");;;;; end;;;;; ;;;;; def write_line(path,pos,str);;;;; if File.file?(path.to_s) == false; raise "No such file."; end;;;;; if File.writable?(path.to_s) == false; raise "File write permission denied by host."; end;;;;; if pos.is_a?(Integer) == false and pos.is_a?(Range) == false; raise "Invalid arguemnts: args[1]: \"pos\", should be Integer or Range"; end ;;;;; if str.to_s.length == 0; raise "Invalid arguments: args[2]: \"str\", should be String of positive length."; end;;;;; begin; cont = File.read(path.to_s);;;;; rescue; raise "Unable to read file.";;;;; end;;;;; cont = cont.split("\n");;;;; if pos.is_a?(Integer) == true;;;;; cont[pos] = str.to_s;;;;; else;;;;; pos.each { |i| cont[i] = str.to_s };;;;; end;;;;; cont = cont.join("\n");;;;; begin; File.write(path.to_s, cont);;;;; rescue; raise "Unable to write file.";;;;; end;;;;; return true;;;;; end ;;;;; ;;;;; ;;;;; def insert_line(path,pos,str);;;;; if File.file?(path.to_s) == false; raise "No such file."; end;;;;; if File.writable?(path.to_s) == false; raise "File write permission denied by host."; end;;;;; if pos.is_a?(Integer) == false; raise "Invalid arguemnts: args[1]: \"pos\", should be Integer."; end ;;;;; if str.to_s.length == 0; raise "Invalid arguments: args[2]: \"str\", should be String of positive length."; end;;;;; begin; cont = File.read(path.to_s);;;;; rescue; raise "Unable to read filw.";;;;; end;;;;; cont = cont.split("\n");;;;; cont.insert(pos,str.to_s);;;;; cont = cont.join("\n");;;;; begin; File.write(path.to_s,cont);;;;; rescue; raise "Unable to write file.";;;;; end;;;;; return true;;;;; end ;;;;; ;;;;;;;;;; def delete_line(path,pos);;;;; if File.file?(path.to_s) == false; raise "No such file."; end;;;;; if File.writable?(path.to_s) == false; raise "File write permission denied by host."; end;;;;; if pos.is_a?(Integer) == false and pos.is_a?(Range) == false; raise "Invalid arguemnts: args[1]: \"pos\", should be Integer or Range"; end ;;;;; begin; cont = File.read(path.to_s);;;;; rescue; raise "Unable to read file.";;;;; end ;;;;; cont = cont.split("\n");;;;; if pos.is_a?(Integer) == true;;;;; cont[pos] = "";;;;; else;;;;; pos.each { |i| cont[i] = "" };;;;; end;;;;; cont = cont.join("\n");;;;; begin; File.write(path.to_s, cont);;;;; rescue; raise "Unable to write file.";;;;; end;;;;; return true;;;;; end ;;;;;;;;;;;;;;; def include? *args ## path, str, matchcase;;;;; if File.file?(args[0].to_s) == false; raise "No such file."; end;;;;; if File.readable?(args[0].to_s) == false; raise "File read permission denied by host."; end;;;;; if args[1].to_s.length == 0; raise "Invalid arguments: args[2]: \"str\", should be String of positive length."; end;;;;; begin; cont = File.read(path.to_s);;;;; rescue; raise "Unable to read file.";;;;; end ;;;;; if args[2] != true; cont = cont.downcase; tag = args[1].to_s.downcase;;;;; else; tag = args[2].to_s;;;;; end;;;;; return cont.include?(tag);;;;; end;;;;;;;;;;;;;;; def empty?(path);;;;; if File.file?(args[0].to_s) == false; raise "No such file."; end;;;;; if File.readable?(args[0].to_s) == false; raise "File read permission denied by host."; end;;;;; empty = nil;;;;; begin; if File.size?(path.to_s) > 0; empty = false; else; empty = true; end;;;;; rescue; raise "Unable to read file.";;;;; end;;;;; return empty;;;;; end;;;;;;;;;; def empty!(path);;;;; if File.file?(args[0].to_s) == false; raise "No such file."; end;;;;; if File.writable?(args[0].to_s) == false; raise "File write permission denied by host."; end;;;;; begin; File.write(path.to_s,"");;;;; rescue; raise "Failed to write file.";;;;; end;;;;; return true;;;;; end;;;;; ;;;;;;;;;; def copy *args #path, newpath;;;;; if File.file?(args[0].to_s);;;;; if File.directory?(args[1].to_s);;;;; if File.file?(args[1].to_s + "/" + args[0].to_s.split("/")[-1].to_s) == false;;;;; fi = File.open(args[0].to_s,"rb") ; cont = fi.read.to_s ; fi.close;;;;; fi = File.open(args[1].to_s + "/" + args[0].to_s.split("/")[-1].to_s,"wb") ; fi.write(cont.to_s) ; fi.close;;;;; return true ;;;;; else ; return "Target directory already contains a file with the same name.";;;;; end;;;;; else ; return "Input target directory is invalid.";;;;; end;;;;; else ; return "No such file.";;;;; end ;;;;; end;;;;; ;;;;;;;;;; def move *args #path, newpath;;;;; if File.file?(args[0].to_s) ;;;;; if File.directory?(args[1].to_s);;;;; if File.file?(args[1].to_s + "/" + args[0].to_s.split("/")[-1].to_s) == false;;;;; fi = File.open(args[0].to_s,"rb") ; cont = fi.read.to_s ; fi.close;;;;; fi = File.open(args[1].to_s + "/" + args[0].to_s.split("/")[-1].to_s,"wb") ; fi.write(cont.to_s) ; fi.close;;;;; File.delete(args[0].to_s);;;;; return true ;;;;; else ; return "Target directory already contains a file with the same name.";;;;; end;;;;; else ; return "Input target directory is invalid.";;;;; end;;;;; else ; return "No such file.";;;;; end ;;;;; end ;;;;; ;;;;; ;;;;; def generate_certificate(filepath);;;;; file_size = File.size(filepath) # Get the size of the file;;;;; total = file_size # Iterate over every byte of the file and add its value to the size;;;;; File.open(filepath, "rb") do |file|;;;;; while byte = file.read(1);;;;; total += byte.unpack('C').first;;;;; end;;;;; end;;;;; certificate = total.to_f / file_size # Divide the total by the size of the file to create the certificate;;;;; return certificate.to_s;;;;; end;;;;; ;;;;; ;;;;; alias :dir? :directory?;;;;;}#8#;#3#;#5#;#3#;#1#;#8#;#3#;#5#;#3#;#8#;#5##integer.rb#5#;#6#;#9#;#9#;#4#;#5#;#6#;#7#;#9#;#6#;#4##integer.rb;;;;;Integer.class_eval{;;;;;;;;;;;;;;; def exponate;;;;; number = self; base = 2; exponent = 2;;;;; while base <= number;;;;; exponent = 2;;;;; while exponent < number;;;;; if base**exponent == number; return [base, exponent]; end;;;;; exponent += 1;;;;; end;;;;; base += 1;;;;; end;;;;; end;;;;;;;;;;;;;;; def factors;;;;; n = self; factor1 = 1; factor2 = n;;;;; (2..Math.sqrt(n)).each do |factor|;;;;; if n % factor == 0;;;;; factor1 = factor;;;;; factor2 = n / factor;;;;; break;;;;; end;;;;; end;;;;; [factor1, factor2];;;;; end;;;;;;;;;; ;;;;; def prime?;;;;; return false if self <= 1;;;;; (2..Math.sqrt(self)).each do |i|;;;;; return false if self % i == 0;;;;; end;;;;; return true;;;;; end;;;;;;;;;; ;;;;; def surname *args;;;;; if args.length == 0; int=self.to_s ; else; int=args[0].to_s; end;;;;; if int.to_s=="0";int="0";;;;; elsif int[-2..-1]=="11" or int[-2..-1] =="12" or int[-2..-1] =="13";int<<"th";;;;; elsif int[-1]=="1";int<<"st";;;;; elsif int[-1]=="2";int<<"nd";;;;; elsif int[-1]=="3";int<<"rd";;;;; else;int<<"th";;;;; end;;;;; return int;;;;; end;;;;; ;;;;; def commas; self.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse; end;;;;; ;;;;;;;;;;};;;;;;;;;;Integer.instance_eval{;;;;;;;;;;};;;;;;;;;;;;;;;#8#;#3#;#5#;#3#;#1#;#8#;#3#;#5#;#3#;#8#;#5##string.rb#5#;#6#;#9#;#9#;#4#;#5#;#6#;#7#;#9#;#6#;#4##string.rb;;;;;String.class_eval{;;;;;;;;;; def shuffle ; return self.split('').shuffle.join('').to_s ; end;;;;; alias :scramble :shuffle;;;;; def base10? ; self.delete("0123456789").empty? ; end;;;;; alias :only_numbers? :base10?;;;;; def base16? ; self.upcase.delete("0123456789ABCDEF").empty? ; end;;;;; alias :only_hex? :base16?;;;;; def base36? ; self.upcase.delete("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").empty? ; end;;;;; def only_letters? ; self.upcase.delete("ABCDEFGHIJKLMNOPQRSTUVWXYZ").empty? ; end ;;;;; def to_binary ##returns a list of the binary byte form of the string from utf8 only(cause ruby);;;;; b = [] ; s = self.to_s.split('');;;;; s.each do |ch|;;;;; b << BINARY[CHARS.index(ch.to_s)] ;;;;; end;;;;; return b.join.to_s;;;;; end;;;;; def from_binary ## works on strings used with .to_b restoring them to ascii characters;;;;; bytes = [] ; s = self.to_s;;;;; until s.to_s.length == 0;;;;; b = s[0..7].to_s ; s = s[8..-1];;;;; bytes << b.to_s;;;;; end;;;;; str = '';;;;; bytes.each do |b|;;;;; str << CHARS[BINARY.index(b.to_s).to_i].to_s;;;;; end;;;;; return str.to_s;;;;; end ;;;;;;;;;; alias :ew? :end_with?;;;;; alias :sw? :start_with?;;;;; ;;;;; ;;;;; ##in building it this way, i can take this and make an actual code parser ;;;;; def splice(b,e) ;;;;; if b.is_a?(String) == false or e.is_a?(String) == false; raise "Arguements require String type.";;;;; elsif b.to_s=="" or e.to_s == ""; raise "Arguements cannot be nilstring.";;;;; end;;;;; s=self ## self inside the loop will not be the string;;;;; if s.length<=(b.to_s.length+e.to_s.length); raise "Base string is too small."; end;;;;; pos=0; stack = false; list=[];;;;; if b.length > e.length ; buffer_length = b.length; else; buffer_length = e.length; end;;;;; buffer = []; buffer_length.times{ buffer << "" };;;;; empty_buffer=[]; buffer_length.times{ empty_buffer << "" } ## again, in the loop we can only refer to vars;;;;; empty_buffer2=[]; buffer_length.times{ empty_buffer2 << "" } ## im really not sure why but id love to know;;;;; tag1=empty_buffer; b.split('').each { |ch| empty_buffer << ch ; empty_buffer.delete_at(0) };;;;; tag2=empty_buffer2; e.split('').each { |ch| empty_buffer2 << ch ; empty_buffer2.delete_at(0) };;;;; loop do ## in this loop s will be self and tag1 & 2 will point to the buffers we want to work with;;;;; if s[pos].to_s==""; break; end ;;;;; buffer << s[pos]; buffer.delete_at(0);;;;; if stack; list << s[pos]; end;;;;; str=buffer.join(''); tag = tag1.join('');;;;; m=true; i=0;;;;; tag.reverse.split('').each{ |ch| if ch.to_s!=str.reverse[i].to_s and ch.to_s != ""; m=false; break; end; i+=1 } ;;;;; if m == true; stack = true; end;;;;; tag = tag2.join('');;;;; m=true; i=0;;;;; tag.reverse.split('').each{ |ch| if ch.to_s!=str.reverse[i].to_s and ch.to_s != ""; m=false; break; end; i+=1 } ;;;;; if m == true; stack = false; end;;;;; pos+=1;;;;; end;;;;; if list.length == 0; return nil ##not nilstring so we can tell the difference on return side;;;;; else; return list.join('')[0..("-"+(e.length+1).to_s).to_i];;;;; end ;;;;; end;;;;;;;;;;# def splice(b, e);;;;; # if !b.is_a?(String) || !e.is_a?(String);;;;; # raise "Arguments require String type.";;;;; # elsif b.empty? || e.empty?;;;;; # raise "Arguments cannot be empty.";;;;; # end;;;;; ;;;;; # s_copy = self.dup;;;;; # if s_copy.length <= (b.length + e.length);;;;; # raise "Base string is too small.";;;;; # end;;;;; ;;;;; # pos = 0;;;;; # stack = false;;;;; # list = [];;;;; ;;;;; # if b.length > e.length;;;;; # buffer_length = b.length;;;;; # else;;;;; # buffer_length = e.length;;;;; # end;;;;; ;;;;; # buffer = Array.new(buffer_length, "");;;;; # empty_buffer = Array.new(buffer_length, "");;;;; # empty_buffer2 = Array.new(buffer_length, "");;;;; ;;;;; # tag1 = empty_buffer;;;;; # b.split('').each do |ch|;;;;; # empty_buffer << ch;;;;; # empty_buffer.delete_at(0);;;;; # end;;;;; ;;;;; # tag2 = empty_buffer2;;;;; # e.split('').each do |ch|;;;;; # empty_buffer2 << ch;;;;; # empty_buffer2.delete_at(0);;;;; # end;;;;; ;;;;; # loop do;;;;; # if s_copy[pos].nil?;;;;; # break;;;;; # end;;;;; ;;;;; # buffer << s_copy[pos];;;;; # buffer.delete_at(0);;;;; ;;;;; # if stack;;;;; # list << s_copy[pos];;;;; # end;;;;; ;;;;; # str = buffer.join('');;;;; # tag = tag1.join('').reverse;;;;; ;;;;; # m = true;;;;; # i = 0;;;;; ;;;;; # tag.split('').each do |ch|;;;;; # if ch != str.reverse[i] && ch != "";;;;; # m = false;;;;; # break;;;;; # end;;;;; ;;;;; # i += 1;;;;; # end;;;;; ;;;;; # if m;;;;; # stack = true;;;;; # end;;;;; ;;;;; # tag = tag2.join('').reverse;;;;; ;;;;; # m = true;;;;; # i = 0;;;;; ;;;;; # tag.split('').each do |ch|;;;;; # if ch != str.reverse[i] && ch != "";;;;; # m = false;;;;; # break;;;;; # end;;;;; ;;;;; # i += 1;;;;; # end;;;;; ;;;;; # if m;;;;; # stack = false;;;;; # end;;;;; ;;;;; # pos += 1;;;;; # end;;;;; ;;;;; # if list.empty?;;;;; # return nil;;;;; # else;;;;; # return list.join('')[0..("-#{e.length + 1}").to_i];;;;; # end ;;;;;# end;;;;;# $str = "hello there<a> asshole</a> fuck you.";;;;; ;;;;; def numerize;;;;; str=self; numbers=[];;;;; str.split('').each{ |ch| ;;;;; n = CHARS.index(ch).to_s;;;;; loop do;;;;; if n.to_s.length < 3; n="0"+n;;;;; else; break;;;;; end;;;;; end;;;;; numbers << n;;;;; };;;;; return numbers.join('') ;;;;; end;;;;; ;;;;; def denumerize;;;;; chars=[];;;;; str=self.split('');;;;; loop do;;;;; if str.length == 0; break; end;;;;; chars<<CHARS[str[0..2].join('').to_i];;;;; 3.times{ str.delete_at(0) };;;;; end;;;;; return chars.join('');;;;; end;;;;; ;;;;; alias :sp :split;;;;;;;;;; ## CODE ISSUE 1 ##;;;;;;;;;; ##one more note, this method is here in class_eval and below in instance_eval, class_eval lets methods work on an object i.e "hello".numerize;;;;; ##where instance_eval lets you do things this way String.numerize("hello");;;;; ##we can probablly remove parse_array from here, im not sure look into it later;;;;; ;;;;; ## incase im dumb enough to come back and ask what this is for, sometimes we store array/hash syntax in files and then eval it to reload data;;;;; ## code could be injected before the data, but theres times we may actually have that as a feature, so heres a method that parses the data with no evaluation of code;;;;; def parse_array *args;;;;; if args.length > 0 ; str = args[0];;;;; else; str = self;;;;; end;;;;; if str.to_s == "[]"; return []; end;;;;; ;;;;; str = str.strip.gsub(/^\[|\]$/, '');;;;; elements = []; current_element = ''; nested_level = 0;;;;; ;;;;; str.each_char do |c|;;;;; if c == ',' && nested_level == 0;;;;; elements << current_element.strip;;;;; current_element = '';;;;; else;;;;; current_element += c;;;;; if c == '['; nested_level += 1;;;;; elsif c == ']'; nested_level -= 1;;;;; end;;;;; end;;;;; end;;;;; ;;;;; elements << current_element.strip;;;;; ;;;;; elements.map do |element|;;;;; if element.start_with?('"') && element.end_with?('"');;;;; element.gsub(/^"|"$/, '');;;;; elsif element.start_with?("'") && element.end_with?("'");;;;; element.gsub(/^'|'$/, '');;;;; elsif element =~ /\A\d+\z/;;;;; element.to_i;;;;; elsif element =~ /\A\d+\.\d+\z/;;;;; element.to_f;;;;; elsif element == 'true' || element == 'false';;;;; element == 'true';;;;; elsif element.start_with?('[') && element.end_with?(']');;;;; self.parse_array(element);;;;; elsif element.start_with?('{') && element.end_with?('}');;;;; self.parse_hash(element);;;;; else;;;;; element;;;;; end;;;;; end;;;;; end;;;;;;;;;;;;;;; def parse_hash *args;;;;; if args.length == 0; str = self;;;;; else; str = args[0];;;;; end;;;;; if str.to_s == "{}"; return {}; end;;;;; ;;;;; str = str.strip.gsub(/^\{|\}$/, '');;;;; pairs = []; current_key = ''; current_value = ''; nested_level = 0;;;;;;;;;; str.each_char do |c|;;;;; if c == '>' && nested_level == 0;;;;; current_key = current_value.gsub(/['":]\s*(\w+)\s*['":]?/, '\1'); current_key = current_key.delete(" =");;;;; current_value = '';;;;; elsif c == ',' && nested_level == 0;;;;; pairs << [current_key, current_value.strip];;;;; current_key = '';;;;; current_value = '';;;;; else;;;;; current_value += c;;;;; if c == '{' || c == '[';;;;; nested_level += 1;;;;; elsif c == '}' || c == ']';;;;; nested_level -= 1;;;;; end;;;;; end;;;;; end;;;;;;;;;; pairs << [current_key, current_value.strip];;;;;;;;;; hash = {};;;;; pairs.each do |pair|;;;;; key = pair[0];;;;; value = pair[1];;;;;;;;;; if value.start_with?('{') && value.end_with?('}');;;;; hash[key] = value.parse_hash;;;;; elsif value.start_with?('[') && value.end_with?(']');;;;; hash[key] = value.parse_array;;;;; elsif value == 'true';;;;; hash[key] = true;;;;; elsif value == 'false';;;;; hash[key] = false;;;;; elsif value =~ /\A\d+\z/;;;;; hash[key] = value.to_i;;;;; elsif value =~ /\A\d+\.\d+\z/;;;;; hash[key] = value.to_f;;;;; else;;;;; hash[key] = value.gsub(/^\"|\"$/, '');;;;; end;;;;; end;;;;; ;;;;; return hash;;;;; end;;;;;;;;;;;;;;;;;;;;};;;;;;;;;;String.instance_eval{;;;;; def numerize(str);;;;; numbers=[];;;;; str.split('').each{ |ch| ;;;;; n = CHARS.index(ch).to_s;;;;; loop do;;;;; if n.to_s.length < 3; n="0"+n;;;;; else; break;;;;; end;;;;; end;;;;; numbers << n;;;;; };;;;; return numbers.join('') ;;;;; end;;;;; ;;;;; def denumerize(str);;;;; chars=[];;;;; str=str.split('');;;;; loop do;;;;; if str.length == 0; break; end;;;;; chars<<CHARS[str[0..2].join('').to_i];;;;; 3.times{ str.delete_at(0) };;;;; end;;;;; return chars.join('');;;;; end;;;;;;;;;; ## these copies of parse hash and array exist to allow calls like String.parse_hash "";;;;; ;;;;; def parse_array(str);;;;; if str.to_s == "[]"; return []; end;;;;; str = str.strip.gsub(/^\[|\]$/, '');;;;; elements = []; current_element = ''; nested_level = 0;;;;; ;;;;; str.each_char do |c|;;;;; if c == ',' && nested_level == 0;;;;; elements << current_element.strip;;;;; current_element = '';;;;; else;;;;; current_element += c;;;;; if c == '['; nested_level += 1;;;;; elsif c == ']'; nested_level -= 1;;;;; end;;;;; end;;;;; end;;;;; ;;;;; elements << current_element.strip;;;;; ;;;;; elements.map do |element|;;;;; if element.start_with?('"') && element.end_with?('"');;;;; element.gsub(/^"|"$/, '');;;;; elsif element.start_with?("'") && element.end_with?("'");;;;; element.gsub(/^'|'$/, '');;;;; elsif element =~ /\A\d+\z/;;;;; element.to_i;;;;; elsif element =~ /\A\d+\.\d+\z/;;;;; element.to_f;;;;; elsif element == 'true' || element == 'false';;;;; element == 'true';;;;; elsif element.start_with?('[') && element.end_with?(']');;;;; self.parse_array(element);;;;; elsif element.start_with?('{') && element.end_with?('}');;;;; self.parse_hash(element);;;;; else;;;;; element;;;;; end;;;;; end;;;;; end;;;;;;;;;;;;;;; def parse_hash(str);;;;; if str.to_s == "{}"; return {}; end;;;;; str = args[0].strip.gsub(/^\{|\}$/, '');;;;; pairs = []; current_key = ''; current_value = ''; nested_level = 0;;;;;;;;;; str.each_char do |c|;;;;; if c == '>' && nested_level == 0;;;;; current_key = current_value.gsub(/['":]\s*(\w+)\s*['":]?/, '\1'); current_key = current_key.delete(" =");;;;; current_value = '';;;;; elsif c == ',' && nested_level == 0;;;;; pairs << [current_key, current_value.strip];;;;; current_key = '';;;;; current_value = '';;;;; else;;;;; current_value += c;;;;; if c == '{' || c == '[';;;;; nested_level += 1;;;;; elsif c == '}' || c == ']';;;;; nested_level -= 1;;;;; end;;;;; end;;;;; end;;;;;;;;;; pairs << [current_key, current_value.strip];;;;;;;;;; hash = {};;;;; pairs.each do |pair|;;;;; key = pair[0];;;;; value = pair[1];;;;;;;;;; if value.start_with?('{') && value.end_with?('}');;;;; hash[key] = value.parse_hash;;;;; elsif value.start_with?('[') && value.end_with?(']');;;;; hash[key] = value.parse_array;;;;; elsif value == 'true';;;;; hash[key] = true;;;;; elsif value == 'false';;;;; hash[key] = false;;;;; elsif value =~ /\A\d+\z/;;;;; hash[key] = value.to_i;;;;; elsif value =~ /\A\d+\.\d+\z/;;;;; hash[key] = value.to_f;;;;; else;;;;; hash[key] = value.gsub(/^\"|\"$/, '');;;;; end;;;;; end;;;;; ;;;;; return hash;;;;; end;;;;;;;;;;;;;;;};;;;;;;;;;;;;;;#8#;#3#;#5#;#3#;#1#;#8#;#3#;#5#;#3#;#8#;#5##time.rb#5#;#6#;#9#;#9#;#4#;#5#;#6#;#7#;#9#;#6#;#4##time.rb;;;;;;;;;;## CODE ISSUE 2 ## ;;;;;## why in gods friggin name are we calling class_eval this way, i wrote this like 5 years ago and ill i remember is there was a valid reason that made things work;;;;;## i belive by calling class.class we are first getting the Time object, then getting the env defined instance of Class from it and adding the methods through there;;;;;## ... but why?;;;;;;;;;;Time.class.class.class_eval{;;;;;;;;;; def parse_seconds(s);;;;; s = s.to_i;;;;; if s < 60 ; [0, 0, s];;;;; elsif s < 3600 ; [0, s / 60, s % 60];;;;; elsif s < 86400 ; [s / 3600, (s / 60) % 60, s % 60];;;;; else;;;;; days = s / 86400;;;;; hours = (s / 3600) % 24;;;;; minutes = (s / 60) % 60;;;;; seconds = s % 60;;;;; [days, hours, minutes, seconds];;;;; end;;;;; end;;;;;;;;;; ## another note, this looks so much better that thick branches checking args;;;;; def stamp(time = Time.now, delimiter = '.');;;;; if time.is_a?(Time);;;;; [time.year.to_s, format("%02d", time.month), format("%02d", time.day),;;;;; format("%02d", time.hour), format("%02d", time.min), format("%02d", time.sec)].join(delimiter);;;;; elsif time.is_a?(String);;;;; t = time.split(delimiter);;;;; Time.new(t[0], t[1], t[2], t[3], t[4], t[5]);;;;; end;;;;; end;;;;;;;;;;};;;;;;;;;;#8#;#3#;#5#;#3#;#1#;#8#;#3#;#5#;#3#;#8#;#5##leval_parser.rb.rb#5#;#6#;#9#;#9#;#4#;#5#;#6#;#7#;#9#;#6#;#4##leval_parser.rb;;;;;## leval_parser.rb v 1.0.2 Linear ruby1.0;;;;;## This parser is designed to run LinearRuby programs from script files (.lrb files).;;;;;## LinearRuby has unimplied rules that can allow programs to run on regular ruby and linear ruby,;;;;;## the rules can be broken but for the most part breaking them doesnt make sense because in ;;;;;## LinearRuby we assume classes are useless and write ruby programs in a linear series of ;;;;;## script blocks that will execute in the order we write them.;;;;;##;;;;;## These script files have a few unimplied rules you are expected to follow to create a proper ;;;;;## linear ruby file:;;;;;## ;;;;;## 1. No classes or glabals are defined, instance variables and constants replace them.;;;;;## 2. The file is composed of blocks of script seperated by '\n\n', so you cannot use it in your code in strings literally, instead use "\n"*2 .;;;;;## 3. 'jumpto' followed by an integer or instance variable jumps program flow to that block in the file, if a second instance variable or expression is included it will be the condition for the jump.;;;;;## 4. when you define methods they are always on main context;;;;;## 5. context is main for every block, the program ends when the counter reaches and runs the last block, or an 'exit' operator is found;;;;;##;;;;;##;;;;;;;;;;# make sure the parser can access main if running outside rubinsystem program.;;;;;if defined?(MAIN) != "constant"; MAIN = self; end;;;;;;;;;;class LinearRubyParser;;;;; def initialize;;;;; @main = MAIN ## link to outside MAIN context;;;;; @state = "init" ## operation state of the parser class;;;;; @level = 0 ## recursion level for :leval also the same as program eval stack level;;;;; @file = nil ## path of current running script;;;;; end;;;;; ;;;;; def main; return @main; end;;;;; def state; return @state; end;;;;; def level; return @level; end;;;;; def file; return @file; end;;;;; ;;;;; ;;;;; #load and eval a LinearRuby file;;;;; def load_file *args ## path, overridecontextwith, passargs;;;;; if File.file?(args[0].to_s) == false; raise "No such file."; end;;;;; if File.readable?(args[0].to_s) == false; raise "File read permission denied by host."; end;;;;; script_path = args[0].to_s ;;;;; if args[1].to_s != ""; context = args[1]; else; context = @main; end;;;;; begin; script = File.read(script_path); @file = script_path;;;;; rescue; raise "Failed to read script file.";;;;; end;;;;; begin; @state = "eval"; @file = "";;;;; return self.leval(script,context,args[2]);;;;; rescue => e; @state = "excep";;;;; raise "Unknown exception state: "+e.to_s+"\n"+e.backtrace.join("\n");;;;; end;;;;; end;;;;; ;;;;; # eval LinearRuby script string;;;;; def leval *args # script, overridecontextwith, passargs;;;;; script = args[0].to_s;;;;; if args.length == 2 and args[1] != ""; context = args[1]; else; context = MAIN; end;;;;; if args.length == 3 and args[2].is_a?(Array); script_args = args[2]; else; script_args = []; end;;;;; running = true;;;;; blocks = script.split("\n\n");;;;; returnval = []; exceptions = []; block = -1;;;;; while running do;;;;; @state = "eval"; @level += 1;;;;; block += 1;;;;; if blocks[block].to_s == ""; running = false; break;;;;; ;;;;; elsif blocks[block].to_s.downcase[0..11] == "dobeforenext";;;;; elsif blocks[block].to_s.downcase[0..9] == "skipnextif";;;;; elsif blocks[block].to_s.downcase[0..7] == "gobackif";;;;; elsif blocks[block].to_s.downcase[0..5] == "jumpto";;;;; ;;;;; if blocks[block].to_s[6..1].delete("\n 0123456789").empty?;;;;; block = ((blocks[block].to_s[6..-1].to_i)-1);;;;; elsif blocks[block].to_s[6..-1].to_s[0] == "@";;;;; begin; var = context.instance_eval(blocks[block].to_s[6..-1]);;;;; if var.is_a?(Integer) == false; raise "Error in file: "[email protected]_s+", block: "+block.to_s+", Invalid jump code, obj is not Integer.; block code: "+blocks[block].to_s; end;;;;; block = var-1;;;;; next;;;;; rescue; raise "Invalid jump code in file:"[email protected]_s+", line: "+block.to_s+"; block: "+"\""+blocks[block].to_s+"\"" ;;;;; end;;;;; end;;;;;;;;;; next;;;;; ;;;;; else;;;;; begin; returnval << context.instance_eval(blocks[block]);;;;; rescue => e; exceptions << e.to_s+"\n"+e.backtrace.join("\n");;;;; end;;;;; end;;;;; end; running = false; @state = "idle"; @level -= 1;;;;; if exceptions == []; return returnval;;;;; else; return [returnval,exceptions];;;;; end;;;;; end;;;;;;;;;;;;;;;;;;;; def parse_file(script);;;;; if File.file?(script) == false; raise "No such file."; end;;;;; script = File.read(script);;;;; self.parse(script);;;;; end;;;;;;;;;;;;;;;# i want to change the names of all variables to be purley alphanumeric in lruby;;;;;# these variable names just cause parsing complexity i dont want when i build the real parser;;;;;;;;;;#[:$-a, :$-p, :$-l, :$@, :$;, :$-F, :$?, :$$, :$&, :$`, :$', :$+, :$=, :$VERBOSE,;;;;;# :$-v, :$stdin, :$stdout, :$>, :$stderr, :$-W, :$DEBUG, :$-w, :$0, :$PROGRAM_NAME,;;;;;# :$-d, :$_, :$~, :$!, :$/, :$,, :$\, :$-0, :$., :$<, :$FILENAME, :$-i, :$*, :$-I, :$:, ;;;;;# :$", :$LOAD_PATH, :$LOADED_FEATURES];;;;;;;;;;## parser needs to be loaded with a default list of ruby;;;;;## classes and globals and their methods so when parsing code they can be recognised;;;;;## apart from defined object calls;;;;;;;;;;;;;;; # parse processes a script with out evaluating it;;;;; def parse(script);;;;; blocks = script.split("\n\n");;;;; stack_keywords = ["def", "if", "case", "class","loop", "while", "for", "begin","{"];;;;; stack_open = [0, 0, 0, 0, 0, 0, 0,0];;;;; last_opened = [];;;;; stack_trace = [] ## keeps track of keywords opened and the ends after them;;;;; line_no = 0;;;;; defined_classes = [];;;;; defined_methods = [];;;;; global_vars = [];;;;; instance_vars = [];;;;; local_vars = [];;;;; statements = [] ## contains an array for each keyword block containing any statements from the block;;;;; unexpected_end = [];;;;; script_ok = true;;;;;;;;;; blocks.each do |block|;;;;; if block.to_s.downcase[0..5] == "jumpto";;;;; # Handle jump statements;;;;; elsif block.to_s == "exit";;;;; # Handle exit statement;;;;; break # done parsing after exit;;;;; else;;;;; lines = block.split(";").join("\n").split("\n");;;;; lines.each do |line| ; line_no += 1;;;;; line = line.gsub(/\s+/, " ");;;;; if line[0] == " "; line = line[1..-1]; end;;;;; ;;;;; if line[0] == "#";;;;; ##comment line;;;;; elsif line[0..3] == "def ";;;;; ;;;;; stack_open[0] += 1;;;;; last_opened << "def"; stack_trace << "def "+line.split(" ")[1..-1].join(" ");;;;; defined_methods << line.split(" ")[1];;;;; elsif line[0..2] == "if ";;;;; stack_open[1] += 1;;;;; last_opened << "if"; stack_trace << "if "+line.split(" ")[1..-1].join(" ");;;;; elsif line[0..4] == "case ";;;;; stack_open[2] += 1;;;;; last_opened << "case"; stack_trace << "case "+line.split(" ")[1..-1].join(" ");;;;; elsif line[0..5] == "class ";;;;; stack_open[3] += 1;;;;; last_opened << "class"; stack_trace << "class "+line.split(" ")[1..-1].join(" ");;;;; defined_classes << line.split(" ")[1] ;;;;; ;;;;; elsif line[0..4] == "loop";;;;; stack_open[4] += 1;;;;; last_opened << "loop"; stack_trace << "loop "+line.split(" ")[1..-1].join(" ");;;;; last_opened << "{"; stack_trace << "loop "+line.split(" ")[1..-1].join(" ");;;;; ;;;;; elsif line =~ /^loop.*\{.*\}\s*$/;;;;; stack_open[4] += 1;;;;; last_opened << "loop";;;;; stack_trace << "loop "+line.split(" ")[1..-1].join(" ");;;;;;;;;; elsif line[0..4] == "while";;;;; stack_open[5] += 1;;;;; last_opened << "while"; stack_trace << "while "+line.split(" ")[1..-1].join(" ");;;;; ;;;;; elsif line[0..2] == "for";;;;; stack_open[6] += 1;;;;; last_opened << "for"; stack_trace << "for "+line.split(" ")[1..-1].join(" ");;;;; ;;;;; elsif line[0..4] == "begin";;;;; stack_open[7] += 1;;;;; last_opened << "begin"; stack_trace << "begin";;;;; elsif line[0..5] == "rescue";;;;; ;;;;; elsif line[0..5] == "else";;;;; ;;;;; elsif line[0..5] == "next";;;;; ;;;;; elsif line[0..5] == "break";;;;;;;;;; elsif line =~ /^@\w+\b\s*==/;;;;; # instance variable with == operator;;;;; elsif line =~ /^@\w+\b\s*\./;;;;; # instance variable with dot operator;;;;; elsif line =~ /^@\w+\b\s*>=/;;;;; # instance variable with >= operator;;;;; elsif line =~ /^@\w+\b\s*<=/;;;;; # instance variable with <= operator;;;;; elsif line =~ /^@\w+\b\s*\+=/;;;;; # instance variable with += operator;;;;; elsif line =~ /^@\w+\b\s*\-=/ ;;;;; # instance variable with -= operator;;;;; elsif line =~ /^@\w+\b\s*=/ # instance variable declaration;;;;; var_name = line.split("=")[0][1..-1] # remove the @ from the var name;;;;; instance_vars << "@"+var_name unless instance_vars.include?("@"+var_name);;;;; ;;;;; elsif line =~ /^\$\w+\b\s*==/;;;;; # global variable with == operator;;;;; elsif line =~ /^\$\w+\b\s*\./;;;;; # global variable with dot operator;;;;; elsif line =~ /^\$\w+\b\s*>=/;;;;; # global variable with >= operator;;;;; elsif line =~ /^\$\w+\b\s*<=/;;;;; # global variable with <= operator;;;;; elsif line =~ /^\$\w+\b\s*\+=/;;;;; # global variable with += operator;;;;; elsif line =~ /^\$\w+\b\s*\-=/ ;;;;; # global variable with -= operator ;;;;; elsif line =~ /^\$\w+\b\s*=/ # global variable declaration;;;;; var_name = line.split("=")[0][1..-1] # remove the $ from the var name;;;;; global_vars << "$"+var_name unless global_vars.include?("$"+var_name);;;;; ;;;;; ;;;;; elsif line =~ /^\w+\b\s*==/;;;;; # instance variable with == operator;;;;; elsif line =~ /^\w+\b\s*\./;;;;; # instance variable with dot operator;;;;; elsif line =~ /^\w+\b\s*>=/;;;;; # instance variable with >= operator;;;;; elsif line =~ /^\w+\b\s*<=/;;;;; # instance variable with <= operator;;;;; elsif line =~ /^\w+\b\s*\+=/;;;;; # instance variable with += operator;;;;; elsif line =~ /^\w+\b\s*\-=/ ;;;;; # instance variable with -= operator;;;;; elsif line =~ /^\w+\b\s*=/ # local variable declaration;;;;; var_name = line.split("=")[0].strip ;;;;; local_vars << var_name unless local_vars.include?(var_name);;;;;;;;;;;;;;;;;;;;;;;;; elsif line.downcase.strip == "end";;;;; # Close the most recent open block;;;;; stack_trace << "end";;;;; if last_opened.any?;;;;; stack_open[stack_keywords.index(last_opened.last)] -= 1;;;;; last_opened.pop;;;;; else; unexpected_end << last_opened[-1].to_s+" @ line "+line_no.to_s;;;;; end;;;;; ;;;;; else;;;;; # Handle other statements ;;;;; ;;;;; end;;;;; end;;;;; ;;;;; # Add a separator to the local variables array between blocks;;;;; local_vars << "" unless local_vars.empty?;;;;; instance_vars << "" unless instance_vars.empty?;;;;; global_vars << "" unless global_vars.empty?;;;;; defined_classes << "" unless defined_classes.empty?;;;;; defined_methods << "" unless defined_methods.empty?;;;;; ;;;;; end;;;;; end;;;;;;;;;; puts "#####################################################################";;;;; puts script.to_s;;;;; puts "#####################################################################";;;;;;;;;; # Check for stack errors;;;;; s=stack_open; s.delete(0);;;;; if s.include?(1);;;;; stack_keywords.each do |k|;;;;; if stack_open[stack_keywords.index(k)] == 1;;;;; puts "ERROR: Stack left open for keyword: "+k.to_s;;;;; script_ok = false;;;;; end;;;;; end;;;;; end ;;;;; if unexpected_end != [];;;;; puts "ERROR: Unexpected 'end' in stack keywords: "+unexpected_end.to_s;;;;; script_ok = false;;;;; end;;;;; defined_classesl = defined_classes; defined_classesl.delete(""); defined_classesl = defined_classesl.length;;;;; defined_methodsl = defined_methods; defined_methodsl.delete(""); defined_methodsl = defined_methodsl.length;;;;; global_varsl = global_vars; global_varsl.delete(""); global_varsl = global_varsl.length ;;;;; instance_varsl = instance_vars; instance_varsl.delete(""); instance_varsl = instance_varsl.length;;;;; local_varsl = local_vars; local_varsl.delete(""); local_varsl = local_varsl.length;;;;; puts "\nParse Results for file: ";;;;; puts "Blocks: "+blocks.length.to_s + " Logical Lines: "+line_no.to_s+"\n";;;;; puts "Size: "+script.to_s.length.to_s+" bytes\n";;;;; puts "";;;;; if defined_classesl > 0;;;;; puts "Defined classes: "+defined_classesl.to_s+": "+defined_classes.join(", ")+"\n";;;;; puts "";;;;; end;;;;; if global_varsl > 0;;;;; puts "Global variables: "+global_varsl.to_s+": "+global_vars.join(", ")+"\n";;;;; puts "";;;;; end;;;;; puts "Defined methods: "+defined_methodsl.to_s+": "+defined_methods.join(", ")+"\n";;;;; puts "";;;;; puts "Instance variables: "+instance_varsl.to_s+": "+instance_vars.join(", ")+"\n";;;;; puts "";;;;; puts "Local variables: "+local_varsl.to_s+": "+local_vars.join(", ")+"\n";;;;; puts "";;;;; puts "Stack trace: "+stack_trace.length.to_s+" :"+stack_trace.to_s+"\n";;;;; puts "";;;;; puts "Script pass: "+script_ok.to_s;;;;; end;;;;;;;;;; ;;;;;end;;;;;;;;;;Parser = LinearRubyParser.new;;;;;$parser = Parser;;;;;;;;;;##require 'openssl';;;;;class Password;;;;; def initialize(string, seed);;;;; @seed = seed;;;;; cipher = OpenSSL::Cipher.new('AES-256-CBC');;;;; cipher.encrypt;;;;; cipher.key = Digest::SHA256.digest(@seed);;;;; @password = cipher.update(string) + cipher.final;;;;; end;;;;; ;;;;; def verify(pass);;;;; cipher = OpenSSL::Cipher.new('AES-256-CBC');;;;; cipher.encrypt;;;;; cipher.key = Digest::SHA256.digest(@seed);;;;; encrypted = cipher.update(pass) + cipher.final;;;;; @password == encrypted;;;;; end;;;;;end#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/launch.rb#1#::#1#::#0#::#0#::#0#::#0#::#1### launch.rb ; file ver 1.1 for rubin 1.0.4 and up ; Rubin system default launcher. Thomas J Slone 2024 11 3;;;;;;;;;;if File.file?(Dir.getwd+"/system/rubin.rb") == true ; load Dir.getwd+"/system/rubin.rb";;;;;else ; raise "Rubin launcher failed to locate the core system file: rubin.rb.\nCurrent work directory: "+Dir.getwd;;;;;end#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/doc.txt#1#::#1#::#0#::#0#::#0#::#0#::#1#;;;;; Documentation for Rubin version 1.0.11;;;;; up to date as of Dec 2024.;;;;; send questions and comments to [email protected];;;;; ;;;;; Introduction.;;;;;;;;;; Requirements:;;;;; - Windows Host (xp/vista/7/10/11);;;;; - Mingw Ruby 1.9.2 or higher (Windows C compiled ruby interpreter.);;;;; - Ruby properly configured (PATH set and .rb file associations);;;;;;;;;; Installation:;;;;; The most common installation method is to use a rubin_installer.rb file to install rubin.;;;;; Install will be made in the work directory if another directory is not specified.;;;;; Other installation methods include using a custom install builder tool or system commands;;;;; to create/install installation package files.;;;;;;;;;; Basics:;;;;; To launch rubin you can double click the launch.rb file located in the top level installation folder.;;;;; This file is called a launcher because it sets up conditions for runtime, different launchers can;;;;; be made to set up a variety of configurations. Launchers can also be executed by other programs such;;;;; as cmd.exe and arguments can be passed into the ruby interpreter that will be available to the system;;;;; after it launches.;;;;;;;;;; Config:;;;;; The system by default loads config.cfg, however if a preconfig file is present i.e preconfig1.cfg, the;;;;; system will load that instead and delete the config after starting up. If there is a file called altconfig.cfg;;;;; the system will use it to point to a config file instead of loading config.cfg. You can call SYSTEM.load_config;;;;; and SYSTEM.save_config to load/save the default config. Other configs can be created/loaded by passing arguments.;;;;; If you run SYSTEM.save_config("configname.cfg") the current config will be saved as a file using the argument as;;;;; its name. To point to your new config file on startup you can either add its name to altconfig.cfg or set a startup;;;;; script that will call to load the config. The final method of specifying config for a startup is to pass the config;;;;; files name as an arguement to the ruby interpreter when running the launcher file, or creating a launcher file that;;;;; will pass the config into the main scopes args variable (args[0]).;;;;;;;;;; Core Files and Directories:;;;;; The default directories created by an install are usually refered to as Core Directories. Not all directories are;;;;; core directories but most will be, these are directories the system expects to exist for runtime such as /app, /class;;;;; and /system. Removing these directories will cause issues with the installation. An install can be configured to have;;;;; more or fewer core directories by the install_builder. These core directories can be accessed a few ways. SYSTEM.dirs;;;;; will return a list of labels for core directories, by passing the label as an arguement the method will return the path.;;;;; The system will also have methods named after the core directories so you can get the paths that way i.e. SYSTEM.homedir;;;;; and lastly, there will be global variable links to these path and instance variables in system as well, these are not;;;;; considered reliable ways for callers to get these paths as they might be reconfigured during runtime, if this happens;;;;; SYSTEM.dirs and systems instance variables will always be the most accurate way to get these paths.;;;;;;;;;; Definition files, Classes and components:;;;;; Definition files can be loaded by the system on startup, definitions.rb in sysdir for example. Definition files can be;;;;; used to modify the ruby interpreter enviornment and objects. They can include any functionality that you do not want;;;;; to implement in your app because you feel it should be an 'out-of-the-box' ruby feature.;;;;; Classes in the classdir can also be loaded on startup providing default objects in an easy to read and edit location.;;;;; Classes should be files containing one class body named after them, they can be used by the system and other callers;;;;; after startup. Class files should not create instances of them selves or other objects nor initialize them.;;;;; Finally, Components exist in two ways, classes embedded in the Rubin system class are considered "embedded components".;;;;; They are initialized automatically on startup and links to them exist as instance variables and methods sharing their names.;;;;; For embedded components these links must be hardcoded since they never change. The second form of components are sysdir;;;;; components. Any file in the system directory besides rubin.rb, daemond.rb or definitions.rb will be considered a sysdir;;;;; component, if configured the system will automatically load and initialize these classes in the scope of the system class.;;;;; Sysdir components should only have the first letter of their name capitalized, because after loading and initializing the;;;;; system will create instance varibales and methods that link to each component and are named after them, so class Component;;;;; for example can be accessed using: @component or SYSTEM.component, components also can include a method called;;;;; 'post_initialize'. On start up and after initialization of each component, the system will check for this method can call it;;;;; if it exists.;;;;;;;;;; Apps and Scripts:;;;;; Apps are files in the appdir. You can see a good example of how an app should work in the 'app_template.rb' file included;;;;; with a new install by default. App files can have any form and do anything however there are some conventions that allow;;;;; the system to interact with and manage apps once running. First, an app file may have any classes but should always end;;;;; with @app = Your_Class.new , when the system runs an app it will grab the object in @app and add it to a list of running;;;;; app objects. In this example Your_Class.new would be the entry point of the app file. App objects can also have the;;;;; post_initialize method, the system will call this method after the object is initialized. This can allow your app to;;;;; seperate behaviors that may require the app to be fully initialized before they can happen. If you want to call;;;;; post_initialize inside your app you can set @post_init = true to let the system know there is no need to call the method.;;;;; You can also set @appshell = true in your app file to tell the system to start a repl shell in the context of the app.;;;;; @post_init, @app and @appshell should be declared in the outer most scope of your app file and not inside objects.;;;;; Keep in mind that app files run inside the context of SYSTEM. When calling SYSTEM.run("app") you can add an array of;;;;; arguements that will be visable in the context of the app file as local-variable args and can be passed to objects in the;;;;; app file. Apps can also be directories, however keep in mind if you have an app file and app dir with the same name, the;;;;; file will be run and the directory will be ignored by SYSTEM.run(). Apps that are directories must have an app file with;;;;; the same name as the directory in its top level. i.e dir: /appdirname , app: /appdirname/appdirname.rb. When the system is;;;;; trying to run an app and finds a directory with the same name, it will look inside for an .rb file and run it.;;;;;;;;;; Scripts are handeled slightly differently than apps, first off scripts can run in internal(SYSTEM) context or external(MAIN);;;;; context. When a script runs externally a new ruby.exe process is started and the script is passed to it. Scripts can contain;;;;; classes and initialize objects but usually scripts are written with static programming styles. Scripts can be run by calling;;;;; SYSTEM.runs("script"). An array of arguments can be added and if true is added after the array the system will run the script;;;;; externally i.e. SYSTEM.runs("script",["arguement"],true). A good example of this in action would be to launch the logmonitor.rb;;;;; script and pass the name of the error log to it, you can call this in SYSTEM context.;;;;; i.e. SYSTEM.runs("logmonitor",["errorlog.log"], true) ;;;;;;;;;; ;;;;; Common commands and behaviors:;;;;; SYSTEM is a global constant and links to the RubinSystem class. MAIN links to the main scope. INSTALLATION_HEADER contains;;;;; information about the install such as location, version and finger print. INSTANCE contains a finger print unique to each;;;;; instance of rubin system running. $debug reflects system debug mode and is either true or false. The default definitions.rb;;;;; files adds some methods such as Dir.dir which gets or sets the work directory depending on if an arguement is passed.;;;;; Dir.view prints the contents of either the work directory or directory passed as an argument. Time.stamp returns a string;;;;; version of a time object and will convert between the two objects if one of them is passed as an argument. String has methods;;;;; to parse array and hash objects from strings with out evaluating them as script. There are many other useful features added;;;;; in definitions.rb and it is recomended to read the file to learn about them. But for app development in general, its ok to;;;;; rely on classes and definition files but it is best to be able to implement all dependant functionality inside your app to;;;;; simplify distrobution.;;;;; ;;;;; SYSTEM.config? will print the system config in an easy to read mannor.;;;;;;;;;; Using config with out a question mark will get/set config values: SYSTEM.config(0,true) , SYSTEM.config("LoadClasses",true);;;;; The first argument is the name or index number and if a second is passed it will set the value.;;;;; Using a config settings name is more reliable than using the index number incase config order gets changed.;;;;; ;;;;; SYSTEM.dir will return the work directory or set it if an argument is passed.;;;;; SYSTEM.dirs returns a list of coredir labels or thier paths if a label is used as an argument.;;;;; SYSTEM.writelog("hello") , SYSTEM.errorlog("wtf!") These methods are used to write to the system logs.;;;;; SYSTEM.apps? Returns a list of apps in the appdir.;;;;; SYSTEM.scripts? Returns a list of scripts. Scripts are in datadir + "/scripts" though this is not a coredir.;;;;; SYSTEM.load_classdir loads all of the files in the class coredir, this usually happens on startup if configured.;;;;;;;;;; System Embedded Components:;;;;; SYSTEM.daemond, @daemond: Daemond is the systems threadpool. You can call SYSTEM.daemond.spawn_thread("script code here");;;;; and the script you pass will be put inside a thread in the threadpool and ran. Apps or system components that frequently;;;;; create numerous threads may find it more sensable to send them to the daemond instead of keeping them inside their own;;;;; class objects.;;;;;;;;;; SYSTEM.install , @install: Installation_Manager does things like creating install packages and installing them. It can also;;;;; create installers using "unpackaged_installer_script.rb" which can run outside of rubin system. Install can also provide;;;;; information about your installation and be used to read/write "hidden_internal_data" which is used to configure coredirs;;;;; for your installation. It contains a list of directories that should restored if deleted and a list of coredirs that your;;;;; system uses.;;;;;;;;;; SYSTEM.shell, @shell: SystemShell is a repl shell, kind of like IRB which allows you to type script and commands into the;;;;; system or other objects after rubin starts up. If the shell is not configured to run it might appear that rubin just opens;;;;; and closes immediatly however configured autostart apps and scripts can still run and if they are coded to, loops not in;;;;; threads for example will keep the system open until they stop running. What you might do is have the very last thing to run;;;;; be a loop that keeps the system open until some condition is met or until you close the window while your threads do work in;;;;; the background. Keep in mind, autostart apps are run in the order they are found in config, then autoscripts are also run in;;;;; the order they appear in config. During a startup the very first thing to be loaded is definitions if configured, then the;;;;; classdir files in no paticular order, then embedded components followed by sysdir components, then the startup script if;;;;; configured(config:StartupShutdownScript:15), then autostart apps, then autostart scripts and finnaly if config;;;;; SystemShellAutoStart index 3 is true, the shell will launch in SYSTEM context.;;;;;;;;;; The system shell takes a few commands, 'exit' will stop the current shell session, SYSTEM.start can start it again or you;;;;; can start a new one inside the current session by calling SYSTEM.shell.start(Object) where Object is the context of the new;;;;; shell session. You can change context inside the shell by entering *context=Object where object is an object in the current;;;;; context, you will always have access to MAIN and SYSTEM from any context. Shells can also save a series of inputs in a;;;;; session and run them again, first to save a session enter SYSTEM.shell.save_session("filename") and the session will be;;;;; saved in the datadir coredir. To load a session you have a few options, SYSTEM.shell.load_session("filename") will return;;;;; and array object containing the session data, you can pass this object into SYSTEM.shell.enter_session([]) or instead of;;;;; an array you can also just pass the name of the file containing the session data. i.e. SYSTEM.shell.enter_session("filename").;;;;; Last thing to be aware of is that you can view the info of all sessions by entering SYSTEM.shell.sessions to return an array;;;;; of session data. To get the index of the current session enter SYSTEM.shell.current_session. You can stop any session by;;;;; entering its index into SYSTEM.shell.stop(0).;;;;;;;;;; SYSTEM.host, @host: Allows the system to interact with the host operating system. It allows things such as execution of;;;;; commands and programs, controlling windows and hardware such as keyboard/mouse/speaker. Host_Manager allows you to;;;;; determine what os the system is running on and allows you to seperate the code that supports one host from another.;;;;; Some times ruby script will be slightly different or host interactions will require different scripts. If you want;;;;; to add linux support this is the component that you will need.;;;;; Right now there is something funny going on with Win32API ruby gem so all hardware functionality had to be striped.;;;;; A fix will come in the future!;;;;; ;;;;; SYSTEM.con, @controller: Allows instances of an installation to interact with eachother through FileIO. A directory;;;;; is used and if configured instances of system can automatically evaluate script placed in the directory addressed to;;;;; specific instances. Through use of windows shared newtork folders, system instances on other machines can point to a;;;;; shared FileIO directory and interact with eachother. Controller is somewhat complex so until it gets its own documentation;;;;; your best bet is to read the component source code located in class Controller of class RubinSystem of /rubin/system/rubin.rb;;;;; ;;;;; These components dont have a super important use yet, barley enough to exist:;;;;;;;;;; SYSTEM.instance, @instance: Return information about the system process such as fingerprint, start time, ect.;;;;; SYSTEM.apps, @apps: Allows complex interactions with app objects.;;;;; SYSTEM.net, @network: Network manager, so far unimplemented.;;;;; SYSTEM.ruby, @ruby: Ruby Manager, so far unimplemented, will allow for queeries and configurations to host ruby install and embedded ruby install with is a new feature comming to version 2.0;;;;; ;;;;; The first and last lines of the rubin.rb system file:;;;;; The first line of the system file declares the INSTALLATION_HEADER information, containing info of the current install location and more.;;;;; The last few lines of the system are marked by a "Hidden_Internal_Data" seperator tag. These lines contain information on;;;;; which directories should be repaired when missing or created on first boot as well as information on required coredirs.;;;;;;;;;;;;;;;;;;;; More to come, im sorry I don't have better documentation of system features. If you need to know more try running a system;;;;; shell and playing around as well as reading the system scripts. A method that might help you is 'local_methods', methods;;;;; shows all methods belonging to an object however local_methods will show methods that were defined in an object class body;;;;; and none of the parent objects methods. You also have ivg, ivs and iv which are short for instance_variable_get,;;;;; instance_variable_set and instance_variables to make things easier. If you have issues dont forget to the the system log;;;;; and system error logs. Thankyou for reading and enjoy working with rubin system!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/launch irb.cmd#1#::#1#::#0#::#0#::#0#::#0#::#1#start irb#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/launch rubin.cmd#1#::#1#::#0#::#0#::#0#::#0#::#1#start ruby "launch.rb" - values of argv#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/data/scripts/systemlogmonitor.rb#1#::#1#::#0#::#0#::#0#::#0#::#1##RubinSystem log monitor v 1.3, 2023.3.3;;;;;#check if we are in a rubin directory;;;;;;;;;;## SOMETHING REALLY FUCKING WEIRD IS HAPPENING WITH THIS LINE;;;;;if Dir.getwd.to_s.downcase.include?("rubin")==false; raise "Cannot locate the 'Rubin' directory."; end;;;;;## so if this line is removed this script can be run as non external but if left in it will fail to split "/rubin" from the file path;;;;;## this line is needed to allow the script to refuse to run if it is not in an actual rubin system;;;;;;;;;;## DEBUG CODE;;;;;;;;;;# puts "DIRGWD: " + Dir.getwd.to_s;;;;;# puts "DIRGWD DOWNCASE: " + Dir.getwd.downcase;;;;;# puts "DIR RUBIN? " + (Dir.getwd.downcase.include?("/rubin")).to_s;;;;;# puts "DIRGW SPLIT " + Dir.getwd.downcase.split("/rubin").to_s;;;;;;;;;;# ##;;;;;# return "LETS FIX THIS SHIT ALREADY";;;;;;;;;;#locate installation and log file;;;;;install_dir=Dir.getwd.to_s.downcase.split("/rubin")[0]+"/rubin";;;;;path=install_dir+"/system/rubin.rb" ;;;;;logpath=install_dir+"/data/logs/systemlog.log";;;;;if File.file?(path) == false; raise "Cannot locate installation."; end;;;;;if File.file?(logpath) == false; "Cannot locate system log."; end;;;;;## get install info and set window title;;;;;begin;;;;;eval(File.read(path).split("\n")[0]);;;;;finger_print=INSTALLATION_HEADER[-1].to_s;;;;;eval(s="`TITLE LOG VIEWER: "+install_dir.to_s+" "+ENV['COMPUTERNAME'].to_s+" "+finger_print+"`");;;;;rescue;`TITLE Rubin system log`;;;;;end;;;;;##prepare screen;;;;;buffer=""; size=0; refresh_delay=1.0;;;;;system("CLS");;;;;## enter file monitoring loop;;;;;loop do;;;;; begin;;;;; s=File.size(logpath);;;;; if s!=size;;;;; size=s;;;;; buffer=File.read(logpath);;;;; system("CLS");;;;; print buffer+"\n";;;;; end;;;;; rescue;;;;; end;;;;; sleep refresh_delay;;;;;end#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/data/scripts/logmonitor.rb#1#::#1#::#0#::#0#::#0#::#0#::#1##check if we are in a rubin directory;;;;;#begin;;;;;;;;;;## refuse to run if launched internnaly.;;;;;if defined?(SYSTEM).to_s != ""; raise "ExternalApp refused to run in non main context: "+self.to_s; end;;;;;;;;;;name = ARGV[1].to_s ## argv is probably already a string at launch;;;;;;;;;;install_dir=Dir.getwd.to_s.downcase.split("/rubin/")[0]+"/rubin";;;;;;;;;;if File.file?(name) == true; logpath = name;;;;;elsif File.file?(install_dir+"/data/logs/"+name) == true;;;;; logpath = install_dir+"/data/logs/"+name;;;;;#elsif File.file?() == true;;;;;#elsif File.file?() == true;;;;;#elsif File.file?() == true;;;;;else; raise "Cannot find file: "+name.to_s;;;;;end;;;;;;;;;;;;;;;##prepare screen;;;;;buffer=""; size=0; refresh_delay=1.0;;;;;system("CLS");;;;;;;;;;## enter file monitoring loop;;;;;loop do;;;;; begin;;;;; s=File.size(logpath);;;;; if s!=size;;;;; size=s;;;;; buffer=File.read(logpath);;;;; system("CLS");;;;; print buffer+"\n";;;;; end;;;;; rescue;;;;; end;;;;; sleep refresh_delay;;;;;end;;;;;;;;;;#rescue => e; puts "Exception: "+e.to_s+"\n"+e.backtrace.join("\n"); puts "Press enter to exit."; gets;;;;;#end#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/data/scripts/unpackaged_installer_script.rb#1#::#1#::#0#::#0#::#0#::#0#::#1### installer version 1.4;;;;;## no package included, paste one into the last line of the file, you can generate one using install.build_package;;;;;;;;;;;;;;;## RubinSystem is a ruby app runtime environment. Multi-Instance, bot controller on Mingw Windows Ruby;;;;;## ## !! WARNING !! If you did not download this script from github or the official website, DO NOT RUN IT!;;;;;## Run this script to install Rubin System in either the current directory or one you enter.;;;;;##;;;;;;;;;;;;;;;#begin;;;;;$version='0';launch_directory=Dir.getwd; launch_time=Time.now;;;;;;;;;;##prompt;;;;;puts "Welcome to the Rubin System installer. Version "+$version.to_s;;;;;puts "";;;;;puts "Dir: "+launch_directory.to_s;;;;;puts "";;;;;puts "Would you like to install to this location? (Y/N)";;;;;inp=gets.chomp.to_s[0].downcase;;;;;if inp=="y"; install_dir=Dir.getwd.to_s;;;;;else;;;;; puts "Enter install directory.";;;;; install_dir=nil;;;;; loop { inp=gets.chomp.to_s; if File.directory?(inp.to_s); install_dir=inp.to_s; break;elsif inp.to_s.downcase == "exit"; exit; else; puts "Invalid directory."; end };;;;;end;;;;;puts "Confirming, you want to install to dir? (Y/N) ; "+install_dir.to_s;;;;;inp=gets.chomp.to_s[0].downcase;;;;;if inp!="y"; puts "Fine, then stop wasting my time...\nThe program will exist in 3 seconds."; sleep 3.0; exit; end;;;;;if File.directory?(install_dir+"/Rubin"); puts "Cannot install here, there is already an installation."; sleep 3.0; exit; end;;;;;;;;;;#load data;;;;;dir=install_dir;;;;;if File.file?($0); p = $0;;;;;elsif File.file?(launch_directory+"/rubin_installer.rb"); p=launch_directory+"/rubin_installer.rb";;;;;else; raise "The installer file cannot locate its self: "+$0.to_s;;;;;end;;;;;f=File.open(p,"r"); data = f.read ; f.close;;;;; ;;;;;#split up package data;;;;;data=data.split(";;;"+";;").join("\n");;;;;maindatasep="#1#::#1"+"#::#0#::#0#::#0#"+"::#1#::#1#";;;;;filenamesep="#1#::#1#::"+"#0#::#0#::#0#"+"::#0#::#1#";;;;;filesep="#1#::#1#::#0#::#0"+"#::#0#"+"::#0#::#0#";;;;;index_sep="#1#::#0#:"+":#0#::#0#::#0#"+"::#0#::#1#";;;;;data=data.split(maindatasep)[-1];;;;;index_string=data.to_s.split(index_sep)[0].to_s;;;;;file_data=data.split(index_sep)[-1];;;;;;;;;;##process files;;;;;file_data=file_data.split(filesep); nfile_data=[];;;;;file_data.each { |d| p=d.split(filenamesep)[0]; di=d.split(filenamesep)[1]; nfile_data<<[p,di] };;;;;file_data=nfile_data;;;;; ;;;;;#proces index;;;;;f = index_string.split("??")[0].split("?");;;;;di = index_string.split("??")[1].split("?");;;;;;;;;;;;;;;#build dirs;;;;;Dir.mkdir(dir.to_s+"/rubin");;;;;di.each { |p| np=dir+"/"+p; Dir.mkdir(np) };;;;;;;;;;# write files;;;;;file_data.each { |fd| p=dir.to_s+"/"+fd[0].to_s; f=File.open(p,"w"); f.write(fd[1].to_s); f.close };;;;;;;;;;## write installation_header;;;;;p=dir.to_s+"/rubin/system/rubin.rb";;;;;f=File.open(p,"r"); dat=f.read; f.close;;;;;old_header=dat.split("\n")[0].split("INSTALLATION_HEADER=")[-1];;;;;old_header=eval(old_header.to_s);;;;;dat=dat.split("\n")[1..-1].join("\n");;;;;version=old_header[2].to_s;;;;;head=["installed",(dir+"/rubin").split("//").join("/"),version,Time.now.to_s,ENV["USER"].to_s,rand(99999999999999).to_s(36)];;;;;str="INSTALLATION_HEADER="+head.to_s;;;;;ndat=str+"\n"+dat;;;;;f=File.open(p,"w"); f.write(ndat); f.close;;;;;;;;;;##;;;;;puts "INSTALL SUCCESS!!!";;;;;puts "The program will exit in 2 seconds";;;;;sleep 2.0;;;;;exit;;;;;;;;;;## INSTALL PACKAGE BELOW#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/data/scripts/install_builder.rb#1#::#1#::#0#::#0#::#0#::#0#::#1### install_builder.rb v1.0;;;;;;;;;;if defined?(SYSTEM) != "constant" ; raise "This script can only be run by an instance of RubinSystem." ; end;;;;;if defined?($homedir) != "global-variable" ; raise "$homedir is not defined! Something might be wrong with your installation." ; end;;;;;;;;;;puts "Welcome to the installation builder tool, enter Y to continue.";;;;;;;;;;if gets.chomp.to_s.downcase[0] != "y" ; raise "You choose not to continue." ; end;;;;;;;;;;puts "Checking your installation...";;;;;;;;;;hidden_internal_data = SYSTEM.install.get_hidden_internal_data;;;;;installation_header = INSTALLATION_HEADER;;;;;if hidden_internal_data == [] or hidden_internal_data.to_s == "" or installation_header.to_s == "" ; raise "Installation builder cannot proceed, there appears to be something wrong with your installation." ; end;;;;;homedir = SYSTEM.dirs("homedir") ; if File.directory?(homedir) == false ; raise "Installation builder cannot proceed, there appears to be something wrong with your installation." ; end;;;;;homedir = homedir.split("/")[0..-2].join("/");;;;;default_index=SYSTEM.install.default_index;;;;;;;;;;puts "Would you like to build a default installer modeled from your current install? (Y/N)";;;;;;;;;;if gets.chomp.downcase[0] == "y" ; mode = "default" ; else ; mode = "custom" ; end;;;;;config_path = false;;;;;;;;;;if mode == "custom";;;;; ##include apps;;;;; puts "Would you like to include appdir in installation? (Y/N/C)";;;;; input = gets.chomp.downcase;;;;; if input[0] == "y";;;;; apps = [] ; appdir = "/rubin/" + SYSTEM.dirs("appdir").downcase.split("/rubin/")[-1];;;;; SYSTEM.apps?.each do |a|;;;;; if eval(default_index[0].to_s.downcase).include?(appdir.downcase + "/" + a.downcase) == false;;;;; default_index[0] << appdir + "/" + a;;;;; end;;;;; apps << a;;;;; end;;;;; puts "Included apps in install index: " + apps.length.to_s;;;;; elsif input[0] == "c";;;;; puts "Enter names of apps to include, enter 'Y' when finished.";;;;; installed_apps = SYSTEM.apps?;;;;; puts "Installed apps: " + installed_apps.to_s;;;;; apps = [];;;;; loop do;;;;; input = gets.chomp.downcase;;;;; if installed_apps.include?(input);;;;; apps << input;;;;; puts "App was added to the installer index.";;;;; elsif input == "y" ; break;;;;; else ; puts "Invalid app name.";;;;; end;;;;; end;;;;; if apps.length > 0;;;;; appdir = "/rubin/" + SYSTEM.dirs("appdir").downcase.split("/rubin/")[-1];;;;; apps.each do |a|;;;;; if eval(default_index[0].to_s.downcase).include?(appdir.downcase + "/" + a.downcase) == false;;;;; default_index[0] << appdir + "/" + a;;;;; end;;;;; end;;;;; end;;;;; end;;;;; ;;;;; ##include classes;;;;; puts "Would you like to include classdir in installation? (Y/N/C)";;;;; input = gets.chomp.downcase;;;;; if input[0] == "y";;;;; classes = [] ; classdir = "/rubin/" + SYSTEM.dirs("classdir").downcase.split("/rubin/")[-1];;;;; Dir.entries(SYSTEM.dirs("classdir")).each do |c|;;;;; if c == "." or c == ".." ; next ; end;;;;; if File.file?(SYSTEM.dirs("classdir") + "/" + c) ; classes << c ; end;;;;; end;;;;; if classes.length > 0;;;;; classes.each do |c|;;;;; if eval(default_index[0].to_s.downcase).include?(classdir.downcase + "/" + c.downcase) == false;;;;; default_index[0] << classdir + "/" + c;;;;; end;;;;; end;;;;; end;;;;; puts "Included classes in install index: " + classes.length.to_s;;;;; elsif input[0] == "c";;;;; puts "Enter names of classes to include, enter 'Y' when finished.";;;;; classes = [] ; installed_classes = [];;;;; Dir.entries(SYSTEM.dirs("classdir")).each do |c|;;;;; if c == "." or c == ".." ; next ; end;;;;; if File.file?(SYSTEM.dirs("classdir") + "/" + c) ; installed_classes << c ; end;;;;; end;;;;; puts "Installed classes: " + installed_classes.to_s;;;;; loop do;;;;; input = gets.chomp.downcase;;;;; if installed_classes.include?(input);;;;; classes << input;;;;; puts "Class was added to the installer index.";;;;; elsif input == "y" ; break;;;;; else ; puts "Invalid class name.";;;;; end;;;;; end;;;;; if classes.length > 0;;;;; classdir = "/rubin/" + SYSTEM.dirs("classdir").downcase.split("/rubin/")[-1];;;;; classes.each do |c|;;;;; if eval(default_index[0].to_s.downcase).include?(classdir.downcase + "/" + c.downcase) == false;;;;; default_index[0] << classdir + "/" + c;;;;; end ;;;;; end;;;;; end;;;;; end;;;;;;;;;; ##include scripts;;;;; puts "Would you like to include scripts in installation? (Y/N/C)";;;;; input = gets.chomp.downcase;;;;; if input[0] == "y";;;;; scripts = [] ; scriptdir = "/rubin/" + (SYSTEM.dirs("datadir").downcase+"/scripts").split("/rubin/")[-1];;;;; SYSTEM.scripts?.each do |s|;;;;; if eval(default_index[0].to_s.downcase).include?(scriptdir.downcase + "/" + s.downcase) == false;;;;; default_index[0] << scriptdir + "/" + s;;;;; scripts << s;;;;; end;;;;; end;;;;; puts "Included scripts in install index: " + scripts.length.to_s;;;;; elsif input[0] == "c";;;;; puts "Enter names of scripts to include, enter 'Y' when finished.";;;;; installed_scripts = SYSTEM.scripts?;;;;; puts "Installed scripts: " + installed_scripts.to_s;;;;; scripts = [];;;;; loop do;;;;; input = gets.chomp.downcase;;;;; if installed_scripts.include?(input);;;;; scripts << input;;;;; puts "Script was added to the installer index.";;;;; elsif input == "y" ; break;;;;; else ; puts "Invalid script name.";;;;; end;;;;; end;;;;; if scripts.length > 0;;;;; scriptdir = "/rubin/" + (SYSTEM.dirs("datadir").downcase+"/scripts").split("/rubin/")[-1];;;;; scripts.each do |s|;;;;; if eval(default_index[0].to_s.downcase).include?(scriptdir.downcase + "/" + s.downcase) == false;;;;; default_index[0] << scriptdir + "/" + s;;;;; end;;;;; end;;;;; end;;;;; end;;;;; ;;;;; ## include sysdir components;;;;; puts "Would you like to include sysdir components in installation? (Y/N/C)";;;;; input = gets.chomp.downcase;;;;; if input[0] == "y";;;;; added_components = [] ; components = [] ; componentdir = "/rubin/" + SYSTEM.dirs("sysdir").downcase.split("/rubin/")[-1];;;;; conts = Dir.entries(SYSTEM.dirs("sysdir"));;;;; conts.each do |f|;;;;; if f == "." or f == ".." ; next ; end;;;;; if ["rubin.rb","daemond.rb","definitions.rb"].include?(f.downcase) ; next ; end;;;;; if File.file?(SYSTEM.dirs("sysdir") + "/" + f) ; components << f ; end;;;;; end;;;;; if components.length > 0;;;;; components.each do |c|;;;;; if eval(default_index[0].to_s.downcase).include?(componentdir.downcase + "/" + c.downcase) == false;;;;; default_index[0] << componentdir + "/" + c ; added_components << c;;;;; end;;;;; end;;;;; end;;;;; puts "Added components to install index: " + added_components.length.to_s;;;;; elsif input[0] == "c";;;;; added_components = [] ; components = [] ; componentdir = "/rubin/" + SYSTEM.dirs("sysdir").downcase.split("/rubin/")[-1];;;;; conts = Dir.entries(SYSTEM.dirs("sysdir"));;;;; conts.each do |f|;;;;; if f == "." or f == ".." ; next ; end;;;;; if ["rubin.rb","daemond.rb","definitions.rb"].include?(f.downcase) ; next ; end;;;;; if File.file?(SYSTEM.dirs("sysdir") + "/" + f) ; components << f ; end;;;;; end;;;;; puts "Enter names of scripts to include, enter 'Y' when finished.";;;;; puts "Installed scripts: " + components.to_s;;;;; loop do;;;;; input = gets.chomp.downcase;;;;; if components.include?(input);;;;; added_components << input;;;;; puts "Component was added to the installer index.";;;;; elsif input == "y" ; break;;;;; else ; puts "Invalid component name.";;;;; end;;;;; end;;;;; if added_components.length > 0;;;;; added_components.each do |c|;;;;; if eval(default_index[0].to_s.downcase).include?(componentdir.downcase + "/" + c.downcase) == false;;;;; default_index[0] << componentdir + "/" + c;;;;; end;;;;; end;;;;; end;;;;; puts "Added components to install index: " + added_components.length.to_s;;;;; end;;;;; ;;;;; ## include specific config;;;;; puts "Would you like to specify default config for installation? (Y/N)";;;;; if gets.chomp.downcase[0] == "y";;;;; puts "Enter name or location of config file.";;;;; loop do;;;;; input = gets.chomp;;;;; if File.file?(SYSTEM.dirs("cfgdir") + "/" + input) and input.downcase[-4..-1] == ".cfg";;;;; config_path = "/rubin/" + SYSTEM.dirs("cfgdir").downcase.split("/rubin/")[-1] + "/" + input ; break;;;;; elsif input.downcase == "exit" ; config_path = false ; break;;;;; else ; puts "No such file.";;;;; end;;;;; end;;;;; else;;;;; config_path = false;;;;; end ;;;;; ;;;;; if config_path != false;;;;; if eval(default_index[0].to_s.downcase).include?(config_path.downcase) == false;;;;; default_index[0] << config_path;;;;; end;;;;; end;;;;; ;;;;; puts "Core directories are as follows: " + hidden_internal_data[1].to_s;;;;; puts "Would you like to continue with these core directories? (Y/N)";;;;; if gets.chomp.downcase[0] != "y";;;;; puts "enter +/- followed by path to add or remove, enter 'exit' when done.";;;;; loop do;;;;; input = gets.chomp.downcase;;;;; if input == "exit" ; break;;;;; elsif input[0] == "+" and input.length > 1;;;;; begin ; array = eval(input[1..-1]);;;;; rescue ; puts "Invalid input, please format as array: ['$dirnam','/rubin/dir']";;;;; end;;;;; if array.is_a?(Array);;;;; if array.length == 2;;;;; if array.include?("") == false;;;;; hidden_internal_data[1] << array;;;;; hidden_internal_data[0] << array[1];;;;; default_index[1] << "/rubin" + array[1];;;;; puts "Core directory was added to installation.";;;;; else ; puts "Invalid input. Contains nil string.";;;;; end;;;;; else ; puts "Invalid input. Length not 2.";;;;; end;;;;; else ; puts "Invalid input. Not array.";;;;; end;;;;; elsif input[0] == "-" and input.length > 1;;;;; begin ; array = eval(input[1..-1]);;;;; rescue ; puts "Invalid input, please format as array: ['$dirnam','/rubin/dir']";;;;; end;;;;; if hidden_internal_data[1].include?(array);;;;; hidden_internal_data[1].delete(array) ;;;;; hidden_internal_data[0][0].delete(array[1]);;;;; default_index[1].delete("/rubin" + array[1]);;;;; puts "Core directory was removed." ;;;;; else ; puts "No such core directory.";;;;; end;;;;; else ; puts "Invalid input.";;;;; end;;;;; end ;;;;; end;;;;; ;;;;; puts "Default file system is as follows: " + hidden_internal_data[0][0].to_s;;;;; puts "Use default file system? (Y/N)";;;;; if gets.chomp.downcase[0] != "y";;;;; puts "Enter +/- to add or remove paths, enter 'exit' when done.";;;;; loop do;;;;; input = gets.chomp;;;;; if input[0] == "+" and input.length > 1;;;;; hidden_internal_data[0][0] << input[1..-1];;;;; default_index[1] << "/rubin" + input[1..-1];;;;; puts "Added file system path.";;;;; elsif input[0] == "-" and input.length > 1;;;;; if hidden_internal_data[0][0].include?(input[1..-1]);;;;; hidden_internal_data[0][0].delete(input[1..-1]);;;;; hidden_internal_data[1].each do |hi|;;;;; if hi[1] == input[1..-1];;;;; hidden_internal_data[1].delete_at(hidden_internal_data[1].index(hi));;;;; end;;;;; end;;;;; default_index[1].delete("/rubin"+input[1..-1]);;;;; puts "Removed file system path.";;;;; else ; puts "Invalid input.";;;;; end;;;;; elsif input.downcase == "exit" ; break;;;;; else ; puts "Invalid input.";;;;; end;;;;; end;;;;; end;;;;; ;;;;;end;;;;;;;;;;puts "Verifying your installation...";;;;;failed = [];;;;;default_index[0].each do |p| ; if File.file?(homedir + p) == false ; failed << p ; end ; end;;;;;if failed.length > 0 ; raise "Unable to build installer, the following files are missing:\n" + failed.join("\n") ; end;;;;;;;;;;installer_location = SYSTEM.dirs("datadir") + "/backups";;;;;puts "About to build your installer at: " + installer_location.to_s;;;;;puts "Is this location acceptable? (Y/N)";;;;;if gets.chomp.downcase[0] != "y";;;;; puts "Enter a location to place the installer.";;;;; loop do;;;;; installer_location = gets.chomp;;;;; if installer_location.downcase == "exit" ; raise "Canceled installation build.";;;;; elsif File.directory?(installer_location) and File.writable?(installer_location) ; break;;;;; else ; puts "Cannot use this location! Please enter a different location or 'exit' to cancel.";;;;; end;;;;; end;;;;;end;;;;;;;;;;puts "Building your installation...";;;;;;;;;;included_files=default_index[0];;;;;included_dir_paths=default_index[1];;;;;files_data=[];;;;;maindatasep="#1#::#1#::#0#::#0#::#0#"+"::#1#::#1#";;;;;filenamesep="#1#::#1#::#0#::#0#::#0#"+"::#0#::#1#";;;;;filesep="#1#::#1#::#0#::#0#::#0#"+"::#0#::#0#";;;;;index_sep="#1#::#0#::#0#::#0#::#0#"+"::#"+"0#::#1#";;;;;##get index file paths;;;;;index_files=[];;;;;included_files.each do |f|;;;;; p=f.to_s.downcase.split("/rubin/")[-1];;;;; index_files << "/rubin/"+p;;;;;end;;;;;;;;;;if config_path != false;;;;; p = "/rubin/" + SYSTEM.dirs("cfgdir").downcase.split("/rubin/")[-1];;;;; included_files.delete(p + "/" + "/config.cfg");;;;;end;;;;;;;;;;## locations of actual resources;;;;;nincluded_files=[];;;;;included_files.each do |f|;;;;; p = f.to_s.downcase.split("/rubin/")[-1];;;;; nincluded_files << SYSTEM.dirs("homedir")+"/"+p;;;;;end;;;;;included_files=nincluded_files;;;;;##get index dir paths ;;;;;index_dirs=[];;;;;included_dir_paths.each do |d|;;;;; p=d.to_s.downcase.split("/rubin/")[-1];;;;; index_dirs << "/rubin/"+p;;;;;end;;;;;##make index string;;;;;index1=index_files.join("?");;;;;index2=index_dirs.join("?");;;;;index=index1+"??"+index2;;;;;## get data of all the files;;;;;files_data=[];;;;;included_files.each do |f|;;;;; f=File.open(f,"r");files_data << f.read ; f.close;;;;;end;;;;;##combine files data with their index paths;;;;;hdat = "##"+hidden_internal_data[0].to_s + "\n##" + hidden_internal_data[1].to_s + "\n##" + [index_files,index_dirs].to_s + "\n##" ; ver = "0";;;;;nfiles_data=[];;;;;files_data.each do |fd|;;;;; i=files_data.index(fd);;;;; p=index_files[i.to_i];;;;; if config_path != false and p.downcase == config_path.downcase;;;;; p = p.split("/")[0..-2].join("/") + "/config.cfg";;;;; end;;;;; if p.downcase == "/rubin/system/rubin.rb";;;;; begin ; ver = eval(fd.to_s.split("\n")[0].split("INSTALLATION_HEADER=")[-1].to_s)[2].to_s ; rescue ; ; end;;;;; fd = fd.to_s.split("#H#;#I#;#D#;#D#;#E#;#N#;#I#;#N#;#T#;#E#;"+"#R#;#N#;#W#;#O#;#R#;#D#;#A#;#S#;#S#;#H#")[0].to_s + "#H#;#I#;#D#;#D#;#E#;#N#"+";#I#;#N#;#T#;#E#;#R#;#N#;#W#;#O#;#R#;#D#;#A#;#S#;#S#;#H#\n"+hdat.to_s;;;;; end;;;;; ;;;;; da=""+p.to_s+filenamesep+fd.to_s;;;;; nfiles_data << da;;;;;end;;;;;;;;;;filespkg = nfiles_data.join(filesep);;;;;final_data = maindatasep.to_s + index.to_s + index_sep.to_s + filespkg.to_s;;;;;final_data=final_data.split("\n").join(";;"+";;;");;;;;;;;;;begin ; f = File.open(SYSTEM.dirs("datadir") + "/scripts/unpackaged_installer_script.rb","r") ; installer_script = f.read.to_s ; f.close;;;;;rescue ; raise "Failed to build installer, unpackaged_installer_script.rb is missing!";;;;;end;;;;;;;;;;installer_script = installer_script.split("$version='0'").join("$version='"+ver.to_s+"'");;;;;final_data = installer_script + "\n" + final_data;;;;;;;;;;begin ; f = File.open(installer_location + "/rubin_installer.rb","w");f.write(final_data); f.close;;;;;rescue ; raise "Unable to build installer file, unable to write to destination: " + installer_location.to_s;;;;;end;;;;;;;;;;puts "Installer build complete, the installer file can be found at: " + installer_location.to_s;;;;;return "Thank you come again!"#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/data/scripts/file_backup.rb#1#::#1#::#0#::#0#::#0#::#0#::#1#internal_data=[["dir", "/rubin/app"], ["dir", "/rubin/class"], ["dir", "/rubin/data"], ["dir", "/rubin/system"], ["dir", "/rubin/data/appdata"], ["dir", "/rubin/data/backups"], ["dir", "/rubin/data/config"], ["dir", "/rubin/data/logs"], ["dir", "/rubin/data/scripts"], ["dir", "/rubin/data/sys"], ["/rubin/system/rubin.rb", "3219234249252195228228195252219237234285216207195204207246183273102315330345348291324324303300102132096102201174141255345303342345141312333327303135345303342354303342141204333297351327303330348345141246351294315330102132096102147138144138147147102132096102150144150156135144162135150150096147162174153144174159153096135144165144144102132096102312333327303135345303342354303342102132096102159348360333354336351327318102279030105105219234249252195228228195252219237234285216207195204207246096291294333354303030030198237237252285219234219252285252219231207096183096252315327303138330333357138348333285345096177096231195219234096183096345303324306096177096219234249252195234201207096183096342291330300120147144144144144144123096177096246255198219234285201237246207285210219228207096183096285285210219228207285285030294333333348285324333309096183096273198237237252285219234219252285252219231207096129096102096174096198237237252096249252195246252219234213138102279030315306096195246213258273147279138348333285345138300333357330297291345303096183183096102348342351303102096177096096108300303294351309096183096348342351303096177096096303324345303096177096096108300303294351309096183096306291324345303096177096096303330300030030105105354303342315306363096342303291300096336303342327315345345315333330030351330324303345345096210315324303138342303291300291294324303189120204315342138309303348357300123030096096294333333348285324333309096180180096102198237237252096207246246237246096174096216333327303300315342096342303291300096336303342327315345345315333330096330333348096309342291330348303300096294363096306315324303096345363345348303327174096102129204315342138309303348357300030096096342291315345303096294333333348285324333309273135147279030303330300030030105105297312303297321096306333342096300303294351309096306324291309030315306096210315324303138306315324303189120204315342138309303348357300129102141300303294351309138306324291309102123096183183096348342351303096333342096210315324303138306315324303189120204315342138309303348357300129102141300291348291141297333330306315309141300303294351309138306324291309102123096177096096108300303294351309096183096348342351303096177096096303330300030030105105354303342315306363096357342315348303096291297297303345345030351330324303345345096210315324303138357342315348291294324303189120204315342138309303348357300123030096096294333333348285324333309096180180096102198237237252096207246246237246096174096216333327303300315342096357342315348303096336303342327315345345315333330096330333348096309342291330348303300096294363096306315324303096345363345348303327174096102129204315342138309303348357300030096096342291315345303096294333333348285324333309138318333315330120102276330102123030303330300030030105105096354303342315306363096345363345348303327096297333342303096306315324303096120348312315345096306315324303123030351330324303345345096210315324303138306315324303189120285285210219228207285285123030096096294333333348285324333309096180180096102198237237252096207246246237246096174096249363345348303327096297333342303096306315324303096297333351324300096330333348096294303096324333297291348303300174096102129285285210219228207285285138348333285345096129096102096261333342321300315342174096102096129096204315342138309303348357300030096096342291315345303096294333333348285324333309138318333315330120102276330102123030303330300030030105105354303342315306363096345363345348303327096297333342303096306315324303096342303291300096291297297303345345030351330324303345345096210315324303138342303291300291294324303189120285285210219228207285285123030096096294333333348285324333309096180180096102198237237252096207246246237246096174096249363345348303327096297333342303096306315324303096300333303345096330333348096336342333354315300303096342303291300096336303342327315345345315333330174096102096129096285285210219228207285285138348333285345030096096342291315345303096294333333348285324333309138318333315330120102276330102123030303330300030030105105354303342315306363096345363345348303327096297333342303096306315324303096357342315348303096291297297303345345030351330324303345345096210315324303138357342315348291294324303189120285285210219228207285285123030096096294333333348285324333309096180180096102198237237252096207246246237246096174096249363345348303327096297333342303096306315324303096300333303345096330333348096336342333354315300303096357342315348303096336303342327315345345315333330174096102096129096285285210219228207285285138348333285345030096096342291315345303096294333333348285324333309138318333315330120102276330102123030303330300030030105297312303297321096141345363345348303327030351330324303345345096210315324303138300315342303297348333342363189120204315342138309303348357300129102141345363345348303327102123030096096294333333348285324333309096180180096102252312303096141345363345348303327096300315342096297333351324300096330333348096294303096324333297291348303300132096336324303291345303096342303315330345348291324324096342351294315330138102030096096342291345315303096294333333348285324333309138318333315330120102276330102123030303330300030030105105354303342315306363096141345363345348303327096342303291300096336303342327315345345315333330030351330324303345345096210315324303138342303291300291294324303189120204315342138309303348357300129102141345363345348303327102123030096096294333333348285324333309096180180096102198237237252096207246246237246096174096249363345300315342096342303291300096336303342327315345345315333330096330333348096309342291330348303300096294363096306315324303096345363345348303327174096102129204315342138309303348357300129102141345363345348303327102030096096342291315345303096294333333348285324333309273135147279030303330300030030105105354303342315306363096141345363345348303327096357342315348303096291297297303345345030351330324303345345096210315324303138357342315348291294324303189120204315342138309303348357300129102141345363345348303327102123030096096294333333348285324333309096180180096102198237237252096207246246237246096174096249363345300315342096357342315348303096336303342327315345345315333330096330333348096309342291330348303300096294363096306315324303096345363345348303327174096102129204315342138309303348357300129102141345363345348303327102030096096342291315345303096294333333348285324333309138318333315330120102276330102123030303330300030030105297312303297321096345363345348303327096297333342303096306315324303096315345096291294324303096348333096294303096324333297291348303300030351330324303345345096204315342138309303348357300138348333285345138300333357330297291345303129102141345363345348303327141342351294315330138342294102096099183096285285210219228207285285030096096294333333348285324333309096180180096102198237237252096207246246237246174096252312303096345363345348303327096297333342303096306315324303096315345096330333348096315330096348312303096324333297291348315333330096315348096315345096303360336303297348303300096348333096294303138096285285210219228207285285174096102129285285210219228207285285138348333285345096129096102096177096207360336303297348303300096324333297291348315333330174096102096129096204315342138309303348357300129102141345363345348303327141342351294315330138342294102030096096342291315345303096294333333348285324333309138318333315330120102276330102123030303330300030030105105096354303342315306363096216237249252285237249030315306096207234258273102237249102279138300333357330297291345303183183102357315330300333357345285330348102096291330300096210315324303138300315342303297348333342363189120102201174141261315330300333357345102123030096096216237249252285237249183102261315330300333357345285234252102030096096294333333348285324333309096180180096102261315330300333357345285234252096333336303342291348315330309096345363345348303327096300303348303297348303300138102030096096315306096210315324303138357342315348291294324303189120102201174141102123096177096096294333333348285324333309096180180096102210351324324096306315324303096345363345348303327096291297297303345345138102030096096303324345303096177096096294333333348285324333309096180180096102228315327315348303300096306315324303096345363345348303327096291297297303345345138102030096096303330300030096096345363345348303327120102252219252228207096246351294315330249363345348303327102129219234249252195228228195252219237234285216207195204207246273150279138348333285345129102096219330345348291330297303174096102129219234249252195234201207138348333285345096129096102096192096102096129096207234258273102255249207246234195231207102279138348333285345129102096177096240219204096102129108108138348333285345129102096204315342174096102129219234249252195228228195252219237234285216207195204207246273147279138348333285345123030303324345315306096210315324303138300315342303297348333342363189120102141312333327303102123030096096216237249252285237249096183096102324315330351360102030096096294333333348285324333309096180180096102228315330351360096333336303342291348315330309096345363345348303327096300303348303297348303300132096297291330330333348096294333333348096294303297291351345303096324315330351360096345351336336333342348096312291345096330333348096363303348096294303303330096291300300303300138102030096096342291315345303096294333333348285324333309138318333315330120102276330102123030303324345303030096096216237249252285237249183102351330321330333357330102030096096294333333348285324333309096180180096102255330321330333357330096312333345348096345363345348303327138102030096096336351348345096102255234225234237261234096216237249252096249267249252207231132096228195255234201216096195234267261195267249189096120267141234123102030096096105315306096309303348345138297312333327336138300333357330297291345303273144279096099183096102363102096177096096342291315345303096294333333348285324333309138318333315330120102276330102123096177096096303330300096096105105096303330291294324303096348312315345096324315330303096291330300096300315345291294324303096348312303096324315330303096294303324333357096348333096342351330096333330096351330321330333357330096312333345348345030096096342291315345303096294333333348285324333309138318333315330120102276330102123030303330300096030030105105297312303297321096315330345348291324324291348315333330096312303291300303342096291330300096315330345348291324324096324333297291348315333330132096351336300291348303096312303291300303342096315306096315330345348291324324096357291345096327333354303300030315306096204315342138309303348357300138348333285345138300333357330297291345303096099183096219234249252195228228195252219237234285216207195204207246273147279138348333285345138300333357330297291345303096096030096096294333333348285324333309096180180096102219330345348291324324291348315333330096357291345096342303297303330348324363096327333354303300138096219330345348291324324096300315342174096102129219234249252195228228195252219237234285216207195204207246273147279138348333285345096129096102096261333342321300315342174096102129204315342138309303348357300138348333285345096030096096294303309315330030096096096096330303357285312333327303300315342096183096204315342138309303348357300030096096096096336291348312183330303357285312333327303300315342129102141345363345348303327141342351294315330138342294102030096096096096300291348291183210315324303138342303291300120336291348312123030096096096096312303291300303342183300291348291138345336324315348120102276330102123273144279030096096096096312303291300303342183312303291300303342138345336324315348120102183102123273135147279030096096096096312303291300303342096183096345303324306138315330345348291330297303285303354291324120312303291300303342123030096096096096312303291300303342273147279183330303357285312333327303300315342030096096096096219234249252195228228195252219237234285216207195204207246183312303291300303342030096096096096312303291300303342183102219234249252195228228195252219237234285216207195204207246183102129312303291300303342138348333285345030096096096096330300291348291183312303291300303342138348333285345129102276330102129300291348291138345336324315348120102276330102123273147138138135147279138318333315330120102276330102123030096096096096306183210315324303138333336303330120336291348312132102357102123177096306138357342315348303120330300291348291123177096096306138297324333345303030096096096096108312333327303300315342183204315342138309303348357300030027294333333348285324333309096180180096102219330345348291324324291348315333330096312303291300303342096315330345348291324324096336291348312096357291345096351336300291348303300138102030096096342303345297351303030096096096096294333333348285324333309096180180096102210291315324303300096348333096351336300291348303096315330345348291324324291348315333330096312303291300303342096315330345348291324324096324333297291348315333330138102030096096303330300030096096315306096108300303294351309096177096096336351348345096294333333348285324333309273135147279096177096096303330300030303324345303096096105105315330345348291324324291348315333330096315345096357312303342303096357303096303360336303297348303300096315348096348333096294303030096096108312333327303300315342096183096204315342138309303348357300030096096294333333348285324333309096180180096102219330345348291324324291348315333330096354303342315306315303300138102030096096315306096108300303294351309096177096096336351348345096294333333348285324333309273135147279096177096096303330300030303330300030030105105096354303342315306363096300291303327333330300096303360315345348345030351330324303345345096210315324303138306315324303189120204315342138309303348357300129102141345363345348303327141300291303327333330300138342294102123030096096306183210315324303138333336303330120204315342138309303348357300129102141345363345348303327141300291303327333330300138342294102132102357102123096177096096306138297324333345303030096096294333333348285324333309096180180096102204291303327333330300096306315324303096357291345096330333348096336342303345303330348132096297342303291348303300096291330096303327336348363096333330303096291345096291096336324291297303312333324300303342138102030096096315306096108300303294351309096177096096336351348345096294333333348285324333309273135147279096177096096303330300030303330300030030105105096354303342315306363096342351294363096354303342345315333330030315306096246255198267285258207246249219237234138345336324315348120102138102123138318333315330120102102123138348333285315096180096147159144030096096294333333348285324333309096180180096102246351294363096354303342345315333330096315345096348333333096333351348300291348303300096348333096294333333348138096246351294363096258303342345315333330174096102129246255198267285258207246249219237234138348333285345030096096342291315345303096294333333348285324333309138318333315330120102276330102123030303324345303030096096294333333348285324333309096180180096102246351294363285258303342345315333330174096102129246255198267285258207246249219237234138348333285345030303330300030030105105297312303297321096312333345348096342351294363030315306096216237249252285237249096183183096102261315330300333357345285234252102030096096336291348312096183096288240195252216288030096096342336291348312096183096306291324345303030096096336291348312138345336324315348120102276276102123138318333315330120102141102123138300333357330297291345303138345336324315348120102177102123138303291297312096300333096372336372030096096096096315306096336138345336324315348120102141102123273147279273144138138153279096183183096102342351294363102030027096096342336291348312096183096336030027096096294333333348285324333309096180180096102216333345348096342351294363096324333297291348303300174096102129336138348333285345030027096096216237249252285246255198267285240195252216096183096342336291348312030027096096294342303291321030027303330300030096096303330300030096096315306096342336291348312096183183096306291324345303030096096096096294333333348285324333309096180180096102255330291294324303096348333096324333297291348303096312333345348096342351294363138102030027216237249252285246255198267285240195252216096183096102102030096096303324345303030096096096096315306096210315324303138306315324303189120216237249252285246255198267285240195252216129102141342351294363138303360303102123030027096096315306096210315324303138345315366303189120216237249252285246255198267285240195252216129102141342351294363138303360303102123030027096096096096294333333348285324333309096180180096102216333345348096342351294363096354303342315306315303300138102030027096096096096216237249252285246255198267285219234252207246240246207252207246096183096216237249252285246255198267285240195252216096129096102141294315330141342351294363138303360303102030027096096303324345303030096096096096096096096096294333333348285324333309096180180096102216333345348096342351294363096297333351324300096330333348096294303096354303342315306315303300138102030096096096096096096096096216237249252285246255198267285219234252207246240246207252207246096183096102102030027096096303330300030027303324345303030027096096294333333348285324333309096180180096102216333345348096342351294363096297333351324300096330333348096294303096354303342315306315303300138102030027303330300030096096303330300030303324345315306096216237249252285237249096183183096102324315330351360102030096096294333333348285324333309096180180096102216333345348096342351294363096297291330330333348096294303096354303342315306315303300096333330096324315330351360096363303348138102030303324345303096105105351330321330333357330096312333345348096333345030096096294333333348285324333309096180180096102216333345348096342351294363096297291330330333348096294303096354303342315306315303300096333330096351330321330333357330096312333345348138102030303330300030030105105096297342303291348303096309324333294291324096324315330321345096348333096201237246207204219246249096306342333327096312315300300303330096315330348303342330291324096300291348291030312300291348096183096210315324303138342303291300120246255198219234285201237246207285210219228207123138345336324315348120102105216105177105219105177105204102129102105177102129102105204105177105207105177105234105177105219105177105102129102234105177105252105177105207105177102129102105246105177105234105177105261105177105237105177105246105102129102177105204105177105195105177105249105177105249105177105216105276330105105102123273135147279138345336324315348120102276330102123273147279273150138138135147279030324315330321345096183096273279030294303309315330030096096297333342303300315342345096183096345303324306138315330345348291330297303285303354291324120312300291348123030096096297333342303300315342345138303291297312096300333096372300372030096096096096294303309315330030027096096345303324306138315330345348291330297303285303354291324120300273144279096129096102183108312333327303300315342129117102129300273147279129102117102123030027096096324315330321345096180180096300273144279030096096096096342303345297351303030027096096294333333348285324333309096180180096102207246246237246174096210291315324303300096348333096297342303291348303096201237246207204219246096324315330321174096102129300273144279096129096102183108312333327303300315342129117102129300273147279129102117102030027303330300030096096303330300030096342303345297351303030096096294333333348285324333309096180180096102207246246237246174096255330291294324303096348333096336291342345303096201237246207204219246249096306342333327096216315300300303330285219330348303342330291324285204291348291102030096096342291315345303096294333333348285324333309138318333315330120102276330102123030096303330300030324315330321345138315330345303342348120144132102108312333327303300315342102123030201237246207204219246249096183096324315330321345030030105105096198237237252096201216207201225096237225030198237237252285252219231207183252315327303138330333357096096096096096096096096096096096096096096096096096096096096030294333333348285324333309096180180096252315327303138330333357138348333285345129102096174096198237237252096249255201201207249249102030030105105345348333342303096348312315345096294333333348345096300291348291096315330096312333327303096345333096345363345348303327096297291330096309342291294096315348096333330297303096345348291342348351336096312291345096294303309351330030306183210315324303138333336303330120108312333327303300315342129102141294333333348324333309138324333309102132102291102123177306138357342315348303120294333333348285324333309138318333315330120102276330102123129102276330102123177306138297324333345303030315306096108300303294351309096183183096348342351303096177096096345096183096102096120204207198255213096231237204207123102096177096096303324345303096177096096345096183096102102096177096096303330300030315306096108300303294351309177096096336351348345096102228333291300315330309096246351294315330249363345348303327138138138096258303342345315333330096102129219234249252195228228195252219237234285216207195204207246273150279138348333285345096129096345138348333285345177096096303330300030030105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030030297324291345345096246351294315330249363345348303327030096096030096096258207246249219237234183219234249252195228228195252219237234285216207195204207246273150279138348333285345096096096105105096228195249252096258207246249219237234096255240213246195204207096150144150156138147150138162030096096096096030096096300303306096315330315348315291324315366303030027105105096297342303291348303096345363345348303327096315330345348291330297303096354291342315291294324303345030096096096096192312333327303300315342183108312333327303300315342030096096096096192291336336183330315324177192348312342303291300345183273279096096096096096105105096342303345303342354303300096306333342096345363345348303327096348333096324291351330297312096291336336345096030027192345312351348300333357330096183096306291324345303030027192345312303324324183330315324096096096096096096096096096096096096096096096096096105105096345363345348303327345312303324324096315345096348312303096297333327336333330303330348345096297324291345345330291327303132096306315360096324291348303342030096096096096192300291303327333330300183330315324096096096096096096096096096096096096096096105105096342303345303342354303300096306333342096327291315330096345363345348303327096348312342303291300336333333324030096096096096192300303306315330315348315333330345183273279030096096096096192291336336345183273279096096096096096096096096096096096096096096096096096096105105096324315345348096333306096291336336096333294318345096291330300096348312342303291300345096324333291300303300096096096096096105096357303096327315309312348096327333354303096348312315345096315330348333096246351294315330174174195336336345096096096120291336336096297333330348342333324324303342123030027192297291297312303096183096273279030096096096096192300291303327333330300096183096330315324096177096192297333330348342333324324303342096183096330315324177096096192315330345348291330297303096183096330315324177096096192315330345348291324324096183096330315324177096096192312333345348096183096330315324177096096192342351294363096183096330315324177096096192330303348357333342321096183096330315324096096096096096030027192297333327336333330303330348345183273279030027192345363345300315342285297333327336333330303330348345096183096273279030027192324333291300303300285297333330306315309096183096273279030027192324333291300303300285345297342315336348345096183096273279030027192324333291300303300285306315324303345096183096273279096096096096096096096096096096105105096324315345348096333306096303354303342363096306315324303096324333291300303300096345315330297303096342351330348315327303138030027192324333291300303300285291336336345096183096273279096096096096096096096096096096096105105096324315345348096333306096291336336096324333291300345096333330096345363345348303327096096105105342303354315345303096348312303345303096348333333096252216219249096219249096249216219252096201237204207096246219213216252096216207246207030096096096096192324333291300303300285297324291345345303345096183096273279096096096096096096096096105105105105105096192297324291345345303345096315345096348312303096330291327303096333306096348312303096354291342315291294324303096357303096291297348351291324324363096351345303030096096096096192324333291300303300285300303306315330315348315333330345096183096273279030027192324333291300303300285291336336345096183096273279030027192342303339351315342303300285306315324303345096183096273279030096096096096192297333330306315309285333354303342315300303096183096306291324345303027030096096303330300030096096030096096300303306096336333345348285315330315348315291324315366303096126291342309345096096105105096297342303291348303096345363345348303327096333294318303297348345030027315306096300303306315330303300189120192240237249252285219234219252219195228219270195252219237234123177096096342303348351342330096102306291324345303102177096096303330300030027030027105105297342303291348303096315330345348291330297303096354291342315291294324303096324315330321345096348333096297333342303300315342345030096096096096315306096201237246207204219246249138324303330309348312096183183096144096177096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096201237246207204219246249096297333351324300096330333348096294303096336342333297303345345303300132096348312315345096303342342333342096345312333351324300096330303354303342096333297297351342138102123030027303324345303030027096096201237246207204219246249138303291297312096300333096372297372030027096096096096294303309315330096177096096249267249252207231138315330345348291330297303285303354291324120102192102096129096297273147138138135147279096129096102096183096102096129096297123096096096096030027096096096096342303345297351303096177096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096210291315324303300096348333096336342333297303345345096201237246207204219246174096102096129096297138348333285345096129096102096315330348333096315330345348291330297303096354291342315291294324303345096306333342096345363345348303327096297324291345345138096249348291342348351336096357315324324096306291315324099102123030027027303330300030027096096303330300030027303330300030027105105096297342303291348303096327303348312333300096324315330321345096348333096297333342303300315342345030096096096096315306096201237246207204219246249138324303330309348312096186096144030027096096201237246207204219246249138303291297312096300333096372297372030027096096096096249267249252207231138315330345348291330297303285303354291324120102300303306096312333327303300315342096177096342303348351342330096192312333327303300315342096177096303330300102123030027096096096096294303309315330096177096096249267249252207231138315330345348291330297303285303354291324120102300303306096102096129096297273147138138135147279096129096102096177096342303348351342330096192102129297273147138138135147279096129096102177096303330300102123030027027342303345297351303096177096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096210291315324303300096348333096297342303291348303096327303348312333300096324315330321096348333096297333342303300315342174096102096129096297138348333285345096129096102138102123030027027303330300030027096096303330300030027303330300030030096096096096105105096327333354303096294333333348324324333309096306342333327096312333327303300315342096315330348333096327291318333342096294333333348096324333309030027294303309315330030027096096315306096210315324303138306315324303189120192312333327303300315342129102141294333333348324333309138324333309102123030027096096096096324333309096183096210315324303138342303291300120192312333327303300315342096129096102141294333333348324333309138324333309102123030027096096096096306096183096210315324303138333336303330120192312333327303300315342129102141294333333348324333309138324333309102132102291102123096177096096306138357342315348303120324333309123096177096096306138297324333345303030027096096096096210315324303138300303324303348303120192312333327303300315342129102141294333333348324333309138324333309102123030027096096303324345303096177096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096198333333348096324333309096306333342096297351342342303330348096294333333348096315345096327315345345315330309099102123030027096096303330300030027342303345297351303096177096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096210291315324303300096348333096327333354303096333354303342096294333333348096324333309138102123030027303330300030030027345303324306138357342315348303324333309120102246351294315330138345348291342348351336174096105105105105105096249267249252207231096249252195246252255240096219249096219234219252219195228219270219234213096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105138102123030027027030027105105096297312303297321096306315324303345363345348303327096306333342096345348291342348351336132096342303336291315342303096291330363096327315345345315330309096297333342303300315342345030027294303309315330030027096096300291348096183096210315324303138342303291300120246255198219234285201237246207285210219228207123138345336324315348120102105216105177105219105177105204102129102105177102129102105204105177105207105177105234105177105219105177105102129102234105177105252105177105207105177102129102105246105177105234105177105261105177105237105177105246105102129102177105204105177105195105177105249105177105249105177105216105276330105105102123273135147279138345336324315348120102276330102123273144279030027096096300291348096183096303354291324120300291348123096177096096300291348183300291348273144279030096096096096096096300291348138303291297312096300333096372306372030027096096096096351330324303345345096210315324303138300315342303297348333342363189120192312333327303300315342129306123030027096096096096096096294303309315330096030027096096096096096096096096204315342138327321300315342120192312333327303300315342129306123030027027027345303324306138303342342333342324333309120102249267249252207231096207246246237246174096231315345345315330309096300315342303297348333342363096342303336291315342303300174096102129192312333327303300315342129306138348333285345123030027027096096342303345297351303096030027027096096303330300030027096096096096303330300030096096096096096096303330300030027342303345297351303177345303324306138303342342333342324333309120102246351294315330138345348291342348351336174096255330291294324303096348333096354303342315306363096210249267249138102123030027303330300030030027105105096345303348351336096297333330306315309096300291348291030027192297333330306315309285330291327303345183273102228333291300201324291345345303345102132102195351348333249348291342348195336336345102132102246303339351315342303300102132030096096096096102249363345348303327249312303324324195351348333249348291342348102132102204303294351309231333300303102132102204291303327333330300204303324291363102132102249312333357228333309261342315348303345102132030096096096096102201348342324234303348300315342102132102228333291300204303306315330315348315333330102132102207354291324351291348303210315324303219237102132102207354291324351291348303210315324303219237240342315330348102132030027102246351294363213303327345102132102195351348333249297342315336348345102132102249312303324324249303345345315333330345102132102228333291300249363345300315342201333327336333330303330348345102132030027102249348291342348351336249312351348300333357330249297342315336348345102132102249363345348303327204291303327333330300210315324303102279030027030027192297333330306315309285300303345297342315336348315333330345183273102102132030027096096096096096096096096096096096096096096096096096096096096096096102102132030027027027027027027096096102102132030027027027027027027096096102102132030027027027027027027096096102102132030027027027027027027096096102102279030027030027192300303306291351324348285297333330306315309183273348342351303132273279132273102294351330300324303342141315330324315330303102132096102333336303330135351342315102132096102330303348141312348348336102132096102306315324303351348315324345102132096102357315330153150333324303102132096102306315300300324303141315327336333342348102132102357315330153150141291336315102279132348342351303132348342351303132147144132306291324345303132102102132348342351303132306291324345303132306291324345303132273279132273279132348342351303132348342351303132273348342351303132348342351303279132348342351303279030096096096096192297333330306315309183192300303306291351324348285297333330306315309030027192324333291300303300285297333330306315309183102102030027030027030027105105096324333291300096297333330306315309030027249267249252207231138357342315348303324333309096102246351294315330138345348291342348351336174096228333333321315330309096306333342096297333330306315309138138138102030027315306096195246213258273150279138348333285345138324303330309348312096186096144096291330300096195246213258273150279138348333285345138300333357330297291345303096099183096102306291324345303102096177096096315306096210315324303138306315324303189120192297306309300315342129102141102129195246213258273150279138348333285345123096177096096192297333330306315309285333354303342315300303096183096195246213258273150279096177096096303330300096177096096303330300027030027315306096192297333330306315309285333354303342315300303096099183096306291324345303030027096096345303324306138357342315348303324333309120102246351294315330138345348291342348351336174096237354303342315300303096297333330306315309096306333351330300174096102129192297333330306315309285333354303342315300303138348333285345123030096096096096096096345303324306138324333291300285297333330306315309120192297333330306315309285333354303342315300303123030027303324345315306096192297333330306315309285333354303342315300303096183183096306291324345303096291330300096210315324303138306315324303189120192297306309300315342096129096102141291324348297333330306315309138297306309102123030027096096294303309315330096177096096336291348312096183096210315324303138342303291300120192297306309300315342129102141291324348297333330306315309138297306309102123030027096096096096315306096210315324303138306315324303189120336291348312123096177096096249267249252207231138324333291300285297333330306315309120336291348312123030027027303324345303030096096096096096096096096096096342291315345303096102102030027027303330300030027096096342303345297351303030027096096096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096210291315324303300096348333096324333297291348303096291324348096297333330306315309138102123030027027249267249252207231138324333291300285297333330306315309030027096096303330300030027303324345303030027096096336342303297333330306315309345096183096273279030027096096204315342138303330348342315303345120192297306309300315342123138303291297312096300333096372300372096177096096300096183096300138348333285345138300333357330297291345303030027096096096096315306096300096183183096102138102096333342096300096183183096102138138102096177096096330303360348096177096096303330300030027027315306096300273144138138168279096183183096102336342303297333330306315309102096291330300096300273135156138138135147279096183183096102138297306309102096177096336342303297333330306315309345096180180096300096177096096303330300030027096096303330300030027096096336342303297333330306315309345096183096336342303297333330306315309345138345333342348030027096096315306096336342303297333330306315309345138324303330309348312096186096144030027096096096096249267249252207231138324333291300285297333330306315309120336342303297333330306315309345273144279123030027027294303309315330096177096096210315324303138300303324303348303120192297306309300315342129102141102129336342303297333330306315309345273144279123030027096096096096342303345297351303030096096096096096096096096096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096210291315324303300096348333096342303327333354303096336342303297333330306315309174096102129336342303297333330306315309345273144279138348333285345123030027027096096249267249252207231138324333291300285297333330306315309027027096096030027027303330300030027096096303324345303030027096096096096249267249252207231138324333291300285297333330306315309030027096096303330300030096096096096303330300030030096096096096105105096324333291300096249267249252207231096201195201216207030096096096096315306096210315324303138306315324303189120192300291348291300315342129102141297291297312303138300291348102123177096096345303324306138324333291300285297291297312303030027303324345303177105096096345303324306138345291354303285297291297312303096096105105297291297312303096315345330348096291324357291363345096351345303300030027303330300030030096096096096105105342303339351315342303096306315324303345030096096096096315306096192297333330306315309273150279096183183096273279096333342096192297333330306315309273150279138348333285345096183183096102102030096096096096096096105105330333096342303339351315342303300096306315324303345030096096096096303324345315306096192297333330306315309273150279138315345285291189120195342342291363123030096096096096096096294303309315330096177096096345096183096192297333330306315309273150279138348333285291138324303330309348312138348333285345096177096096342303345297351303096177096096345096183096102144102096177096096303330300030096096096096096096249267249252207231138357342315348303324333309120102246351294315330138345348291342348351336174096102096129096345096129096102342303339351315342303300096306315324303345096357315324324096294303096324333291300303300096102123030027096096192297333330306315309273150279138303291297312096300333096372306372030027096096096096294303309315330030027096096096096096096342303339351315342303096096306138348333285345096177096192324333291300303300285306315324303345180180306096177096096192342303339351315342303300285306315324303345096180180096306030027096096096096096096249267249252207231138357342315348303324333309120102246351294315330138345348291342348351336174096246303339351315342303300096306315324303174096102129306138348333285345123030027096096096096342303345297351303096183186096303030027096096096096096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096210291315324303300096348333096342303339351315342303096306315324303174096102096129096306138348333285345096129096102276330207342342333342174096102129096303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123129102276330102123030027096096096096303330300030027096096303330300030027096096315306096108300303294351309096177096096315306096345138348333285315096099183096192324333291300303300285306315324303345138324303330309348312096177096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096210291315324303300096348333096342303339351315342303096345333327303096306315324303345174096195297348351291324324363096324333291300303300174096102129096192324333291300303300285306315324303345138324303330309348312138348333285345096129096102141102096129096345138348333285345123096177096096303330300096177096096303330300030096096096096303324345303096105105096219234258195228219204096258195228255207030096096096096096096192297333330306315309273150279096183096273279030027096096249267249252207231138345291354303285297333330306315309120192324333291300303300285297333330306315309123096096030027096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096201333330306315309096150096246303339351315342303300210315324303345096297333330348291315330303300096315330354291324315300096300291348291132096315348096357291345096342303345303348138096102123030096096096096303330300030030027105105324333291300141315330345348291324324096342351294363309303327345030027315306096192297333330306315309273147147279138315345285291189120195342342291363123030027096096315306096192297333330306315309273147147279138324303330309348312096186096144030027096096096096315306096108300303294351309177096096336351348345096102228333291300315330309096246351294363096213303327345138138138102177096096303330300030027096096096096342303339351315342303300183192297333330306315309273147147279030027096096096096309303327345183288309303327096324315345348288177309303327345183309303327345138345336324315348120102276330102123030027096096096096309303327306315324303345183273279177309303327345138303291297312096369372309372096309303327306315324303345180180309138345336324315348120102096120102123273144279375030096096096096096096096096342303339351315342303300138303291297312096300333096372342372030027027096096354096183096342303339351315342303096342138348333285345030027096096096096096096315306096309303327306315324303345138315330297324351300303189120342123183183306291324345303096291330300096354096099183096348342351303030096096096096096096096096096096096096345303324306138357342315348303324333309120102246351294315330138345348291342348351336174096195348348303327336348315330309096348333096315330345348291324324096342351294363309303327174096102129342123027027030027027096096096096315306096108300303294351309177096096336351348345096102246351294363096309303327096315345096294303315330309096315330345348291324324303300174096102129342129102096138138138102177096096303330300030027027096096096096294303309315330030027027096096096096096096309303327306315324303096300333030096096096096096096096096096096096096096096096096345333351342297303096117312348348336345174141141342351294363309303327345138333342309117030027027027027315306096342138348333285345096183183096102357315330153150141291336315102096177096096342096183096102357315330153150135291336315102096177096096303330300096105105348312315345096315345096357312363096357303096345348315297321096348333096330291327315330309096297333330354303330348315333330345132096246207231237258207096252216219249096228219234207096219210096252216207267096207258207246096204207201219204207096252237096210219264096252216207096234195231207030096096096096096096096096096096096096096096096096309303327096342138348333285345030096096096096096096096096096096096096096096303330300030027027096096096096096096342303339351315342303096342138348333285345096177030027027027096096192324333291300303300285309303327345096180180096342030027027096096096096342303345297351303030027027096096096096096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096246351294363096309303327096297333351324300096330333348096294303096315330345348291324324303300174096102129342138348333285345123030096096096096096096096096096096096096303330300030027027096096303324345303177342303339351315342303096342138348333285345096177096096192324333291300303300285306315324303345096180180096342030027027096096303330300030027096096096096303330300030027096096303330300030027303324345315306096192297333330306315309273147147279096183183096306291324345303030027096096105105330333096342351294363309303327345030027303324345303096105105096219234258195228219204096258195228255207030027096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096201333330306315309096147147096246351294363213303327345096297333330348291315330303300096291330096315330354291324315300096354291324351303138096219348096357291345096342303345303348138102123030027096096192297333330306315309273147147279183273279030027096096345303324306138345291354303285297333330306315309120192324333291300303300285297333330306315309123030027303330300096096030027096096096096096096096096030027027096096030027105105096324333291300096300303306315330315348315333330345027096096030096096096096315306096192297333330306315309273168279096183183096273279096333342096192297333330306315309273168279138348333285345138300333357330297291345303096183183096102306291324345303102096333342096192297333330306315309273168279138348333285345096183183096102102030027096096105105330333096300303306315330315348315333330345030027303324345315306096192297333330306315309273168279138348333285345138300333357330297291345303096183183096102348342351303102096333342096192297333330306315309273168279138315345285291189120195342342291363123030027096096300303306315330315348315333330345096183096273279030027096096315306096192297333330306315309273168279138315345285291189120195342342291363123096177096300303306315330315348315333330345096183096192297333330306315309273168279096177096303324345303096177096300303306315330315348315333330345096180180096102300303306315330315348315333330345138342294102096177096303330300096030027096096300303306315330315348315333330345138303291297312096300333096372300372030027096096096096294303309315330030027027096096294303309315330096177096096306096183096210315324303138333336303330120192345363345300315342096129096102141102096129096300138348333285345132102342102123096177096096345297342315336348096183096306138342303291300096177096096306138297324333345303030027027096096342303345297351303096177096096342291315345303096102210291315324303300096348333096342303291300096306315324303138102030027027096096303330300030027027096096231195219234138315330345348291330297303285303354291324120345297342315336348123096177096096192324333291300303300285306315324303345180180102300303306315330315348315333330345138342294102096177096096192324333291300303300285300303306315330315348315333330345096180180096102300303306315330315348315333330345138342294102030096096096096096096096096096096249267249252207231138357342315348303324333309120102246351294315330138345348291342348351336174096195336336324315303300096300303306315330315348315333330174096102096129096300138348333285345123030027027342303345297351303096183186096303030027027096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096204303306315330315348315333330174096102096129096300138348333285345096129096102096336342333300351297303300096291330096303360297336348315333330138276330102129303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123123030027027303330300030027096096303330300030027096096315306096108300303294351309096177096096336351348345096102228333291300303300096300303306315330315348315333330345174096102096129096192324333291300303300285300303306315330315348315333330345138348333285345096177096096303330300030027303324345303096096105105096219234258195228219204096258195228255207030027096096345303324306138303342342333342324333309120102246351294315330138345348291342348351336174096201333330306315309096168096228333291300204303306315330315348315333330096297333330348291315330303300096291330096315330354291324315300096354291324351303132096315348096357291345096342303345303348138102123030027096096192297333330306315309273168279183348342351303030027096096345303324306138345291354303285297333330306315309120192324333291300303300285297333330306315309123030027303330300030027030027105105096228333291300096297324291345345303345030027315306096192297333330306315309273144279138348333285345096183183096102102096333342096192297333330306315309273144279096183183096273279030027096096105105096330333096297324291345345303345030027303324345315306096192297333330306315309273144279138348333285345138300333357330297291345303096183183096102348342351303102030027096096249267249252207231138324333291300285297324291345345300315342030027303324345315306096192297333330306315309273144279138315345285291189120195342342291363123030027096096249267249252207231138324333291300285297324291345345300315342120192297333330306315309273144279123030096096096096303324345303096105105096219234258195228219204096258195228255207030027096096249267249252207231138303342342333342324333309096102246351294315330138345348291342348351336174096201333330306315309096144096228333291300201324291300300204315342096297333330348291315330303300096291330096315330354291324315300096354291324351303132096315348096357291345096342303345303348138102030027096096192297333330306315309273168279096183096348342351303030027096096345303324306138345291354303285297333330306315309120192324333291300303300285297333330306315309123030027303330300030096030096096096096105105096324333291300096303327294303300300303300096297333327336333330303330348345030027192303327294303300300303300285297333327336333330303330348345096183096273279030027192303327294303300300303300285297333327336333330303330348285333294318303297348345096183096273279030027105105096219210096267237255096231195225207096201216195234213207249096252237096207231198207204204207204096201237231240237234207234252249096267237255096231255249252096255240204195252207096252216219249096228219249252030027273174192300291303327333330300132096174192291336336285297333330348342333324324303342132096174192345312303324324132096174192315330345348291330297303132096174192312333345348132096174192315330345348291324324132096174192297333330348342333324324303342132096174192330303348357333342321132174192342351294363279138303291297312096369096372297372096192303327294303300300303300285297333327336333330303330348345096180180096297096375030096096096096030027192300291303327333330300183249363345348303327204291303327333330300138330303357030027192291336336285297333330348342333324324303342096183096195336336345138330303357030027192345312303324324183249363345348303327249312303324324138330303357030027192315330345348291330297303096183096219330345348291330297303138330303357030096096096096192312333345348096183096216333345348285231291330291309303342138330303357030027192315330345348291324324096183096219330345348291324324291348315333330285231291330291309303342138330303357030027192297333330348342333324324303342096183096201333330348342333324324303342138330303357030027192330303348357333342321096183096234303348357333342321285231291330291309303342138330303357120123030027192342351294363096183096246351294363285231291330291309303342138330303357120123030096096096096249267249252207231138357342315348303324333309120102246351294315330138345348291342348351336174096102129192303327294303300300303300285297333327336333330303330348345138324303330309348312138348333285345129102096303327294303300300303300096345363345348303327096297333327336333330303330348345096357303342303096315330315348315291324315366303300138096102129192303327294303300300303300285297333327336333330303330348345138348333285345123030027030096096096096303297183273192300291303327333330300132192291336336285297333330348342333324324303342132192345312303324324132192315330345348291330297303132192312333345348132192315330345348291324324132192297333330348342333324324303342132192330303348357333342321132192342351294363279030027303297138303291297312096369096372297372096192303327294303300300303300285297333327336333330303330348285333294318303297348345096180180096297096375030027027030027105105096324333291300096345363345300315342096297333327336333330303330348345096315306096297333330306315309303300030027192345363345300315342285297333327336333330303330348345183273279030027192297333327336333330303330348285333294318303297348345183273279030027192297333327336333330303330348345183273279030096096096096336342303315354345183345303324306138315330345348291330297303285354291342315291294324303345096096030096096096096315306096192297333330306315309273147156279183183348342351303030027030027096096297183204315342138303330348342315303345120192345363345300315342123177096096297138300303324303348303120102138102123177096096297138300303324303348303120102138138102123030027096096297138303291297312096369372297372096351330324303345345096297138348333285345138300333357330297291345303183183102342351294315330138342294102096333342096297138348333285345138300333357330297291345303183183102300291303327333330300138342294102096333342096297138348333285345138300333357330297291345303273144138138171279183183102300303306315330315348315333330102096291330300096297138348333285345138300333357330297291345303273135153138138135147279096183183096102138342294102096177096192297333327336333330303330348345180180297138348333285345177096096192345363345300315342285297333327336333330303330348345180180297138348333285345177303330300375030027096096315306096192297333327336333330303330348345138324303330309348312186144030027096096096096249267249252207231138357342315348303324333309120102246351294315330138345348291342348351336174096228333291300315330309096345363345348303327096297333327336333330303330348096306315324303345174096102129192297333327336333330303330348345138348333285345123030027096096096096192297333327336333330303330348345138303291297312096300333096372297372030027096096096096096096294303309315330030096096096096096096096096096096096096324333291300096192345363345300315342129102141102129297177096096192324333291300303300285306315324303345096180180096297138348333285345030027027027294303309315330030027027027096096249267249252207231138315330345348291330297303285303354291324120102192102096129096120297138348333285345138300333357330297291345303138345336324315348120102138342294102123273144279138348333285345123096129096102183102096129096120297138348333285345138300333357330297291345303138345336324315348120102138342294102123273144279138348333285345123138297291336315348291324315366303096129096102138330303357102123030027027027096096354096183096102192102096129096120297138348333285345138300333357330297291345303138345336324315348120102138342294102123273144279138348333285345123030027027027342303345297351303096183186096303030027027027096096345303324306138303342342333342324333309120102246351294315330138345348291342348351336174096249267249204219246096297333327336333330303330348096297333351324300096330333348096294303096297342303291348303300174096102096129096303138348333285345096129096102276330102096129096303138294291297321348342291297303138318333315330120102276330102123123030027027027303330300030027096096096096096096342303345297351303096183186096303096177315306096108300303294351309177096096096336351348345096303138348333285345177096096303330300030027027096096096096345303324306138303342342333342324333309120102246351294315330138345348291342348351336174096249363345348303327096297333327336333330303330348096324333291300096342303345351324348303300096315330096303360297336303348315333330174096102129297138348333285345129102096102129303138348333285345129102096096096102129303138294291297321348342291297303138318333315330120102276330102123123030027096096096096096096303330300030027096096096096303330300096030027096096303330300030027030027096096105105315345333324291348303096330303357324363096297342303291348303300096297333327336333330303330348096315330345348291330297303096354291342315291294324303345030027096096336333345348315354345183345303324306138315330345348291330297303285354291342315291294324303345096177096096336342303315354345138303291297312096369096372315354372096336333345348315354345138300303324303348303120315354123096375027096096030096096096096096096192297333327336333330303330348345183336333345348315354345030027096096192297333327336333330303330348345138303291297312096300333096372297372096177096096345303324306138315330345348291330297303285303354291324120102192297333327336333330303330348285333294318303297348345096180180096102129297138348333285345123096177096096303330300030027096096030027096096315306096336333345348315354345138324303330309348312186144177096096249267249252207231138357342315348303324333309120102246351294315330138345348291342348351336174096219330315348315291324315366303300096102129336333345348315354345138324303330309348312138348333285345129102096297333327336333330303330348345138096102129192297333327336333330303330348345138348333285345123096177096096303330300030027096096324333291300303300285297333327336096183096273279030096096096096096096105105297342303291348303096345363345300315342096297333327336333330303330348096327303348312333300096324315330321345030096096096096096096315306096192345363345300315342285297333327336333330303330348345138324303330309348312096186096144030096096096096096096096096192345363345300315342285297333327336333330303330348345138303291297312096300333096372297372030096096096096096096096096096096297096183096297138348333285345138300333357330297291345303138345336324315348120102138342294102123273144279030027096096096096096096294303309315330030027027096096096096315306096120303354291324120102300303306315330303300189120192102129297129102123102123123138348333285345096183183096102315330345348291330297303135354291342315291294324303102030027096096096096096096096096096096294303309315330096177096096249267249252207231138315330345348291330297303285303354291324120102300303306096102096129096297138348333285345096129096102096177096342303348351342330096192102096129096297138348333285345096129096102096177096096303330300102123096177096324333291300303300285297333327336096180180096297138348333285345096177096249267249252207231138357342315348303324333309120102246351294315330138345348291342348351336174096249267249204219246096297333327336333330303330348096324333291300303300174096102096129096297138348333285345123030027027096096096096096096342303345297351303096177096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096210291315324303300096348333096297342303291348303096327303348312333300096324315330321096348333096297333327336333330303330348174096102096129096297138348333285345123030027027096096096096096096303330300030027096096096096096096096096303324345303030027096096096096096096096096096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096201291330330333348096306315330300096297333327336333330303330348174096102096129096297138348333285345096129096102132096315348096327291363096330333348096312291354303096294303303330096336342333336303342324363096324333291300303300138102123030027027096096096096096096330303360348030027096096096096096096096096303330300030027027096096342303345297351303096177096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096210291315324303300096348333096336342333297303345345096345363345300315342096297333327336333330303330348096330291327303174096102096129096297138348333285345123030027027096096303330300030096096096096096096096096303330300030027027315306096324333291300303300285297333327336138324303330309348312096186096144096177096096315306096108300303294351309096177096096336351348345096102228333291300303300096249267249204219246096297333327336333330303330348345174096102129324333291300303300285297333327336138348333285345096177096096303330300096177096096303330300030096096096096096096096303330300030096030027303330300030027030096096096096105105096210219234195228096249252195246252255240096201216207201225249030096030096027345303324306138357342315348303324333309120102246351294315330138345348291342348351336174096246351294315330249363345348303327096315330315348315291324315366291348315333330096297333327336324303348303300138102123030027342303348351342330096144027030096096303330300030096096105105303330300096333306096345348291342348351336096327303348312333300030096096030096030096096300303306096345348291342348351336030096096096096351330324303345345096300303306315330303300189120192240237249252285219234219252219195228219270195252219237234123096183183096102315330345348291330297303135354291342315291294324303102096030027096096192240237249252285219234219252219195228219270195252219237234096183096348342351303030027096096192345348291342348351336285348315327303096183096252315327303138330333357030027096096030027096096105105336333345348285315330315348096303327294303300300303300096297333327336333330303330348345030096096096096096096315306096192303327294303300300303300285297333327336333330303330348345138324303330309348312096186096144030027096096096096315297183273279030027027192303327294303300300303300285297333327336333330303330348285333294318303297348345138303291297312096300333096372297372030027096096096096096096315306096297138327303348312333300345138315330297324351300303189120174336333345348285315330315348315291324315366303123030027096096096096096096096096297138336333345348285315330315348315291324315366303030027027027315297096180180096297138297324291345345138348333285345030027096096096096096096303330300030027096096096096096096192297333327336333330303330348345096180180096120102192102129297138297324291345345138348333285345138300333357330297291345303138348333285345138345336324315348120102342351294315330345363345348303327174174102123273135147279123138348333285345363327096096096096096105105096330333096330303303300096306333342096348312303345303096342303291324324363030027096096096096303330300030027096096096096249267249252207231138357342315348303324333309120102246351294315330138345348291342348351336174096102129315297138324303330309348312138348333285345129102096303327294303300300303300096345363345348303327096297333327336333330303330348345096357303342303096336333345348096315330315348315291324315366303300174096102129315297138348333285345123030027096096303330300030027096096105105336333345348285315330315348096333348312303342096297333327336333330303330348345030027096096315306096192297333327336333330303330348285333294318303297348345138324303330309348312096186096144030027096096096096192297333327336333330303330348285333294318303297348345138303291297312096300333096372297372030027096096096096096096315306096297138327303348312333300345138315330297324351300303189120174336333345348285315330315348315291324315366303123030027096096096096096096096096297138336333345348285315330315348315291324315366303030027027096096096096345303324306138357342315348303324333309120102246351294315330138336333345348285315330315348315291324315366303174096249363345348303327096297333327336333330303330348096336333345348096315330315348315291324315366303300174096102129297138348333285345123030027096096096096096096303330300030027096096096096303330300030027096096303330300030027096096030027096096105105096342351330096345348291342348351336096345297342315336348030027096096345348291342348351336285345297342315336348345096183096273279030027096096315306096192297333330306315309273147159279273144279138348333285345138300333357330297291345303096183183096102306291324345303102096333342096192297333330306315309273147159279273144279096183183096273279096333342096192297333330306315309273147159279273144279138348333285345096183183096102102030027096096096096105105096330333096345348291342348351336096345297342315336348345030027096096303324345315306096192297333330306315309273147159279273144279138348333285345096183183096102348342351303102030027096096096096315306096210315324303138306315324303189120192300291348291300315342096129096102141345297342315336348345141345348291342348351336138342294102123096177096096345348291342348351336285345297342315336348345096180180096102345348291342348351336138342294102096177096096303330300030027096096303324345315306096192297333330306315309273147159279273144279138348333285345096183183096102252246255207102030027096096096096204315342138303330348342315303345120192300291348291300315342096129096102141345297342315336348345102123138303291297312096300333096372300372030027027096096315306096300138348333285345096183183096102138102096333342096300138348333285345096183183096102138138102096333342096210315324303138306315324303189120192300291348291300315342096129096102141345297342315336348345141102096129096300138348333285345123096183183096306291324345303096333342096300138348333285345138300333357330297291345303273135153138138135147279096099183096102138342294102096333342096300138348333285345138300333357330297291345303273144138138162279096099183096102345348291342348351336102096177096330303360348030027027096096303324345303096177096096345348291342348351336285345297342315336348345096180180096300030027027096096303330300030027027303330300030027096096303324345315306096192297333330306315309273147159279273144279138315345285291189120195342342291363123030027096096096096192297333330306315309273147159279273144279138303291297312096300333096372306372096177096096315306096210315324303138306315324303189120192300291348291300315342096129096102141345297342315336348345141102096129096306138348333285345123096177096096345348291342348351336285345297342315336348345096180180096306138348333285345096177096096303330300096177096096303330300030027096096303324345303096105105096219234258195228219204096258195228255207030027096096096096192297333330306315309273147159279273144279096183096273279030027027249267249252207231138345291354303285297333330306315309030027027249267249252207231138303342342333342324333309120102246351294315330138336333345348285315330315348315291324315366303174096201333330306315309096147159132144096249348291342348351336249312351348300333357330249297342315336348345096312291300096291330096315330354291324315300096354291324351303132096315348096312291300096348333096294303096342303345303348138102123030027096096303330300030027096096315306096345348291342348351336285345297342315336348345138324303330309348312096186096144030027096096096096249267249252207231138357342315348303324333309120102246351294315330138336333345348285315330315348315291324315366303174096210333351330300096102129345348291342348351336285345297342315336348345138324303330309348312138348333285345096129096102096345348291342348351336096345297342315336348345138102123030027027345348291342348351336285345297342315336348345138303291297312096300333096372345372096177096249267249252207231138342351330345120345138348333285345123096177096096303330300030027096096303330300027096096030027096096030027096096105105096342351330096345348291342348351336096291336336345030027096096315306096192297333330306315309273147279096183183096273279096333342096192297333330306315309273147279138348333285345096183183096102102096333342096192297333330306315309273147279138348333285345138300333357330297291345303096183183096102306291324345303102030027096096096096105105096330333096291351348333345348291342348096291336336345030027096096303324345303030027096096096096315306096192297333330306315309273147279138315345285291189120195342342291363123030096096096096096096096096096096249267249252207231138357342315348303324333309120102228333291300315330309096102129192297333330306315309273147279138324303330309348312138348333285345129102096345348291342348351336096291336336345138102123030027027096096192297333330306315309273147279138303291297312096300333096372291336336372096177096096249267249252207231138342351330120291336336123096177096096303330300027096096030027027303324345303096105105096219234258195228219204096258195228255207030027027096096192297333330306315309273147279096183096273279030027027096096249267249252207231138345291354303285297333330306315309030027027096096249267249252207231138303342342333342324333309120102246351294315330138336333345348285315330315348315291324315366303174096201333330306315309096147096195351348333345348291342348195336336345096312291300096291330096315330354291324315300096354291324351303132096315348096312291300096348333096294303096342303345303348138102123030027027303330300030027096096303330300030027096096105105096342351330096291336336345096291351348333345348291342348096294303312291354315333342030027096096315306096192291336336345138324303330309348312096186096144030027096096096096192291336336345138303291297312096300333096372291372030027096096096096096096315306096291273153279096183183096330315324096177096096330303360348096177096096303330300030027027096096315306096291273153279138327303348312333300345138315330297324351300303189120174291351348333345348291342348285294303312291354315333342123030027027096096096096294303309315330096177096096291273153279138291351348333345348291342348285294303312291354315333342030027027027342303345297351303177096096249267249252207231138303342342333342324333309120102246351294315330138336333345348285315330315348315291324315366303174096102096129096291273144279138348333285345096129096102195336336096291351348333345348291342348285294303312291354315333342096336342333300351297303300096291330096303360297303336348315333330174096102096129096303138348333285345096129096102276330102096129096303138294291297321348342291297303138318333315330120102276330102123123030027027027303330300030027027096096303330300030027096096096096303330300030027096096303330300030027096096030027096096105105096249252195246252255240096201237231240228207252207030027096096345303324306138357342315348303324333309120102246351294315330138336333345348285315330315348315291324315366303174096249363345348303327096345348291342348351336096345351297297303345345306351324324138102123030096027096096315306096108300303294351309177096096030027096096096096336351348345096102249348291342348351336096297333327336324303348303138096219330345348291330297303174096102129345303324306138315330345348291330297303138315300138348333285345129102096102129345303324306138348333285345030027096096096096105336351348345096102249348291342348303300096351336096315330096102129120252315327303138330333357135198237237252285219234219252285252219231207123138348333285345273144138138153279129102096345303297333330300345138096102129252315327303138330333357138348333285345138345336324315348120102096102123273144138138147279138318333315330120102096102123129102132096228333291300303300096102096129096192324333291300303300285306315324303345138324303330309348312138348333285345129102096306315324303345138102030096096096096096096303330300030027096096030027096096105105096342351330096291351348333096345297342315336348345030027096096315306096192297333330306315309273147150279138348333285345096183183096102102096333342096192297333330306315309273147150279096183183096273279096333342096192297333330306315309273147150279138348333285345138300333357330297291345303096183183096306291324345303030027096096096096105105096330333096291351348333096345297342315336348345030027096096303324345315306096192297333330306315309273147150279138315345285291189120195342342291363123030027096096096096291351348333345297342315336348345096183096273279030027027192297333330306315309273147150279138303291297312096300333096372345372030027027096096315306096210315324303138306315324303189120192300291348291300315342096129096102141345297342315336348345141102096129096345138348333285345123096177096096291351348333345297342315336348345096180180096345138348333285345030027027096096303324345303096177096096249267249252207231138303342342333342324333309120102246351294315330138336333345348285315330315348315291324315366303174096195351348333345297342315336348096096324315345348303300096315330096297333330306315309273147150279096300333303345096330333348096303360315345348174096102096129096345138348333285345123030027027096096303330300030027027303330300030096096096096096096096096315306096291351348333345297342315336348345138324303330309348312096186096144030027027096096291351348333345297342315336348345138303291297312096300333096372345372096177096096249267249252207231138342351330345120345123096177096096303330300030027027303330300030027096096303324345303096105105096219234258195228219204096258195228255207030027027192297333330306315309273147150279096183096273279030027027345303324306138345291354303285297333330306315309120192324333291300303300285297333330306315309123030027096096096096249267249252207231138303342342333342324333309120102246351294315330138345348291342348351336174096201333330306315309273147150279096297333330348291315330345096315330354291324315300096300291348291174102096129192297333330306315309273147150279138348333285345273144138138150144279129102138096219348096312291300096348333096294303096342303345303348138102123027096096030027096096303330300030027096096030027096096105105096342351330096345312303324324030027096096315306096192297333330306315309273153279138348333285345138300333357330297291345303183183102348342351303102030027096096096096345303324306138357342315348303324333309120102246351294315330138336333345348285315330315348315291324315366303174096249348291342348315330309096345363345348303327096345312303324324138102123030027096096096096315306096108330333285345312303324324096099183096348342351303030027027096096315306096108300303294351309177096096336351348345096102249348291342348315330309096345363345348303327096345312303324324138102177096096303330300030027027096096345303324306138345312303324324138345348291342348120345303324306123030027027303324345303096177096096249267249252207231138357342315348303324333309120102108330333285345312303324324096315345096345303348132096345321315336336303300096345312303324324138102123030027027303330300030027096096303330300030027096096030096096096096303330300030096096303330300030096096105105096303330300096333306096345348291342348351336096327303348312333300030096096105105105105105105105105105105105105105105105105105105105105105105105105030030096096300303306096297324345177096096249267249252207231138345312303324324138297324345177096096303330300030096096300303306096309303348285297333330306315309177342303348351342330096192297333330306315309177303330300030096096300303306096324333291300303300285297333327336333330303330348345177342303348351342330096192297333327336333330303330348345177096096303330300030096096300303306096324333291300303300285306315324303345177096096342303348351342330096192324333291300303300285306315324303345177096096303330300030096096030030096096105105096297342303291348303096327303348312333300096324315330321345096348333096303327294303300300303300096345363345348303327096297333327336333330303330348345132096357303096327315309312348096345348342303291327096324315330303096348312315345096351336348333096357312303342303096303327294303300300303300096297333327336333330303330348345096291342303096297342303291348303300096291294333354303030096096294303309315330030096096096096300303306096345312303324324096177096096342303348351342330096192345312303324324096177096096303330300030096096096096300303306096315330345348291324324096177096096342303348351342330096192315330345348291324324096177096096303330300030027300303306096300291303327333330300096177096096342303348351342330096192300291303327333330300096177096096303330300030096096096096300303306096342351294363096177096096342303348351342330096192342351294363096177096096303330300030096096096096300303306096330303348357333342321096177096096342303348351342330096192330303348357333342321096177096096303330300030096096096096300303306096312333345348096177096096342303348351342330096192312333345348096177096096303330300030096096096096300303306096315330345348291330297303096177096096342303348351342330096192315330345348291330297303096177096096303330300030096096096096300303306096297333330348342333324324303342096177096096342303348351342330096192297333330348342333324324303342096177096096303330300030027300303306096291336336345177096096342303348351342330096192291336336285297333330348342333324324303342096177096096303330300030096096096096291324315291345096174297333330096174297333330348342333324324303342030096096096096291324315291345096174330303348096174330303348357333342321030096096342303345297351303177096345303324306138303342342333342324333309120102246351294315330096357291345096351330291294324303096348333096300303306315330303096327303348312333300096324315330321345096348333096291324324096324333291300303300096297333327336333330303330348345138102123030096096303330300030030030096096300303306096345312333357285297333330306315309030096096096096345348342183102102177096096297306309183273279177096096315183144177096096192297333330306315309285330291327303345138303291297312096369096372330372096297306309096180180096315138348333285345129102096096102129330138348333285345129102183096102129192297333330306315309273315279138348333285345177096096315096129183096147096375030027345348342096180180096102246351294315330096345363345348303327096297333330306315309174096102129192324333291300303300285297333330306315309138348333285345129102276330276330102177096096345348342096180180096297306309138318333315330120102276330102123138348333285345129102276330102177096096342303348351342330096345348342030096096303330300096096030096096291324315291345096174297333330306315309189096174345312333357285297333330306315309030030096096300303306096300315342096126291342309345030096096096096315306096291342309345138324303330309348312096183183096144096177096096342303348351342330096231195219234138300315342030027303324345303096177096096342303348351342330096231195219234138300315342120291342309345273144279138348333285345123030027303330300030096096303330300030096096030096096300303306096300315342345096126291342309345030096096096096315306096291342309345138324303330309348312096183183096144096177096096300315342345096183096273279096177096201237246207204219246249138303291297312096369096372300372096300315342345096180180096300273147138138135147279096375096177096096342303348351342330096300315342345096177096096303330300030027315306096201237246207204219246249138315330297324351300303189120102108102129291342309345273144279138348333285345138300333357330297291345303123030027096096294303309315330096177096096342303348351342330096303354291324120102192102129291342309345273144279138348333285345138300333357330297291345303123030027096096342303345297351303096177096096342291315345303096102195330096303342342333342096333297297351342303300096357312315324303096324333333321315330309096351336096201237246207204219246174096102129291342309345273144279138348333285345096129096102132096363333351096327291363096297333330345315300303342096342303330291327315330309096315348096348333096291354333315300096348312315345096303342342333342138102030027096096303330300030027303324345303096177096096342303348351342330096306291324345303030027303330300030096096303330300030096096030096096300303306096291336336345189096126291342309345030096096096096315306096291342309345138324303330309348312096186096144030027096096297312303297321096183096273279030027096096315306096291342309345273144279138315345285291189120249348342315330309123096333342096291342309345273144279138315345285291189120249363327294333324123096177096297312303297321096183096273291342309345273144279138348333285345279030027096096303324345315306096291342309345273144279138315345285291189120195342342291363123096177096096315306096291342309345273144279138324303330309348312096183183096144096177096096342303348351342330096330315324096177096096303324345303096177096096291342309345273144279138303291297312096300333096372291372096177096297312303297321096180180096291138348333285345096177096096303330300096177096096303330300030027096096303324345303096177096096342291315345303096102219330354291324315300096291342309351327303330348345096306333342096246351294315330138291336336345189102030027096096303330300030027096096291336336345096183096273279030027096096204315342138303330348342315303345120192291336336300315342123138303291297312096300333096372306372030027027315306096306138348333285345096183183096102138102096333342096306138348333285345096183183096102138138102096177096096330303360348096177096303330300030027027315306096306138348333285345138300333357330297291345303273135153138138135147279096183183096102138342294102096291330300096210315324303138306315324303189120192291336336300315342096129096102141102096129096306138348333285345123096177096096291336336345096180180096306138300333357330297291345303030027027303324345315306096210315324303138300315342303297348333342363189120192291336336300315342096129102141102096129096306123096291330300096210315324303138306315324303189120192291336336300315342096129096102141102096129096306096129096102141102096129096306096129096102138342294102123096177096291336336345096180180096306138300333357330297291345303096129096102138342294102030027027303330300030027096096303330300030027096096306333351330300096183096348342351303030027096096297312303297321138303291297312096300333096372291372030027096096096096315306096291138348333285345138300333357330297291345303273135153138138135147279096099183096102138342294102096177096291096183096291096129096102138342294102096177096096303330300030027096096096096315306096291336336345138315330297324351300303189120291138300333357330297291345303123096183183096306291324345303096177096096306333351330300096183096306291324345303096177096294342303291321096177096096303330300030027096096303330300030027096096342303348351342330096306333351330300030027303324345303030027096096291336336345096183096273279030027096096204315342138303330348342315303345120192291336336300315342123138303291297312096300333096372306372030027096096096096315306096306138348333285345096183183096102138102096333342096306138348333285345096183183096102138138102096177096096330303360348096177096303330300030027096096096096315306096306138348333285345138300333357330297291345303273135153138138135147279096183183096102138342294102096291330300096210315324303138306315324303189120192291336336300315342096129096102141102096129096306138348333285345123096177096096291336336345096180180096306138300333357330297291345303030027096096096096303324345315306096210315324303138300315342303297348333342363189120192291336336300315342096129102141102096129096306123096291330300096210315324303138306315324303189120192291336336300315342096129096102141102096129096306096129096102141102096129096306096129096102138342294102123096177096291336336345096180180096306138300333357330297291345303096129096102138342294102030027096096096096303330300030027096096303330300030027096096342303348351342330096291336336345096030027303330300030096096303330300030030096096300303306096345297342315336348345189096126291342309345030096096096096315306096291342309345138324303330309348312096183183096147030096096096096096096315306096291342309345273144279138348333285345138300333357330297291345303273135153138138135147279096099183096102138342294102096177096291096183096291342309345273144279138348333285345096129096102138342294102096177096303324345303096177096291096183096291342309345273144279138348333285345096177096303330300030027096096342303348351342330096210315324303138306315324303189120192300291348291300315342096129096102141345297342315336348345141102096129096291123030096096096096303324345315306096291342309345138324303330309348312096183183096144030027096096291096183096273279030027096096204315342138303330348342315303345120192300291348291300315342129102141345297342315336348345102123138303291297312096300333096372306372030027096096096096315306096306138348333285345096183183096102138102096333342096306138348333285345096183183096102138138102096177096330303360348096177096303330300030027027315306096210315324303138306315324303189120192300291348291300315342129102141345297342315336348345141102129306138348333285345123096177096096315306096306138348333285345138300333357330297291345303273135153138138135147279096183183096102138342294102096177096096291096180180096306096177096096303330300096177096096303330300030027096096303330300030027096096342303348351342330096291030096096096096303324345303096177096096342291315345303096102219330354291324315300096291342309351303327303330348345096306333342096246351294315330138345297342315336348345189102030027303330300030096096303330300030030096096300303306096324333309345189096126291342309345030096096096096315306096291342309345138324303330309348312096183183096147030096096096096096096315306096291342309345273144279138348333285345138300333357330297291345303273135156138138135147279096099183096102138324333309102096177096291096183096291342309345273144279138348333285345096129096102138324333309102096177096303324345303096177096291096183096291342309345273144279138348333285345096177096303330300030027096096342303348351342330096210315324303138306315324303189120192324333309300315342096129096102141102096129096291123030096096096096303324345315306096291342309345138324303330309348312096183183096144030027096096291096183096273279030027096096204315342138303330348342315303345120192324333309300315342123138303291297312096300333096372306372030027096096096096315306096306138348333285345096183183096102138102096333342096306138348333285345096183183096102138138102096177096330303360348096177096303330300030027027315306096210315324303138306315324303189120192324333309300315342129102141102129306138348333285345123096177096096315306096306138348333285345138300333357330297291345303273135156138138135147279096183183096102138324333309102096177096096291096180180096306096177096096303330300096177096096303330300030027096096303330300030027096096342303348351342330096291030096096096096303324345303096177096096342291315345303096102219330354291324315300096291342309351303327303330348345096306333342096246351294315330138324333309345189102030027303330300030096096303330300030030096096300303306096297333330306315309285306315324303345189096126291342309345030096096096096315306096291342309345138324303330309348312096183183096147030096096096096096096315306096291342309345273144279138348333285345138300333357330297291345303273135156138138135147279096099183096102138297306309102096177096291096183096291342309345273144279138348333285345096129096102138297306309102096177096303324345303096177096291096183096291342309345273144279138348333285345096177096303330300030027096096342303348351342330096210315324303138306315324303189120192297306309300315342096129096102141102096129096291123030096096096096303324345315306096291342309345138324303330309348312096183183096144030027096096291096183096273279030027096096204315342138303330348342315303345120192297306309300315342123138303291297312096300333096372306372030027096096096096315306096306138348333285345096183183096102138102096333342096306138348333285345096183183096102138138102096177096330303360348096177096303330300030027027315306096210315324303138306315324303189120192297306309300315342129102141102129306138348333285345123096177096096315306096306138348333285345138300333357330297291345303273135156138138135147279096183183096102138297306309102096177096096291096180180096306096177096096303330300096177096096303330300030027096096303330300030027096096342303348351342330096291030096096096096303324345303096177096096342291315345303096102219330354291324315300096291342309351303327303330348345096306333342096246351294315330138297333330306315309285306315324303345189102030027303330300030096096303330300030030096096300303306096291324348297333330306315309189030096096096096315306096210315324303138306315324303189120192297306309300315342129102141291324348297333330306315309138297306309102123096183183096306291324345303096177096096342303348351342330096306291324345303096177096096303330300030096096096096294303309315330096177096315306096210315324303138306315324303189120192297306309300315342096129096102141102096129096120210315324303138342303291300120192297306309300315342129102141291324348297333330306315309138297306309102123123123096177096096342303348351342330096306096177096096303324345303096177096096342303348351342330096306291324345303096177096096303330300030096096096096342303345297351303030027096096249267249252207231138303342342333342324333309120102246351294315330138291324348297333330306315309189174096210291315324303300096348333096342303291300096291324348297333330306315309096336333315330348303342096306315324303138102123030027096096342291315345303096102210291315324303300096348333096342303291300096291324348297333330306315309096336333315330348303342096306315324303138102030096096096096303330300030096096303330300030030096096300303306096336342303297333330306315309189030096096096096306333351330300096183096273279030027204315342138303330348342315303345120192297306309300315342123138303291297312096300333096372306372096177096096315306096306138348333285345138300333357330297291345303273144138138168279096183183096102336342303297333330306315309102096291330300096210315324303138306315324303189120192297306309300315342129102141102129306123096177096306333351330300096180180096306096177096303330300096177096096303330300030027342303348351342330096306333351330300138345333342348030096096303330300030096096030096096300303306096357342315348303324333309096126291342309345105096291300096333336348315333330096348333096336342315330348030027315306096210315324303138306315324303189120192324333309300315342129102141345363345348303327324333309138324333309102123183183306291324345303177306183210315324303138333336303330120192324333309300315342129102141345363345348303327324333309138324333309102132102357102123177306138297324333345303177303330300030027348345183252315327303138330333357138348333285345138345336324315348120102096102123273144138138147279138318333315330120102138102123138345336324315348120102174102123138318333315330120102138102123138345336324315348120102135102123138318333315330120102138102123030027345348342183102276330102129348345129102174096102129219234249252195234201207138348333285345129102174096102129291342309345273144279138348333285345030027306183210315324303138333336303330120192324333309300315342129102141345363345348303327324333309138324333309102132102291102123177306138357342315348303120345348342123177306138297324333345303030027294303309315330030027315306096291342309345273147279138348333285345138300333357330297291345303183183102348342351303102096291330300096192297333330306315309273162279138348333285345096099183096102348342351303102177096096336351348345096102276330102129291342309345273144279138348333285030027303324345315306096249267249252207231138297333330306315309120102249312333357228333309261342315348303345102123096183183096348342351303030027096096336351348345096291342309345273144279138348333285345030027303330300030027342303345297351303030027303330300030096096303330300030030096096300303306096303342342333342324333309120327345309123096096030027348345183252315327303138330333357138348333285345138345336324315348120102096102123273144138138147279138318333315330120102138102123138345336324315348120102174102123138318333315330120102138102123138345336324315348120102135102123138318333315330120102138102123030027345348342183102276330102129348345129102174096102129219234249252195234201207138348333285345129102174096102129327345309138348333285345030027345348342150183102276330102129348345129102174096102129219234249252195234201207138348333285345129102174096195330096303342342333342096333297297351342303300174096102129327345309138348333285345030027306183210315324303138333336303330120192324333309300315342129102141303342342333342324333309138324333309102132102291102123177306138357342315348303120345348342138348333285345123177306138297324333345303027030027315306096249267249252207231138297333330306315309120102204303294351309231333300303102123096183183096348342351303030027096096306183210315324303138333336303330120192324333309300315342129102141345363345348303327324333309138324333309102132102291102123177306138357342315348303120345348342150138348333285345123177306138297324333345303027030027096096336351348345096102207246246237246174096102096129096327345309138348333285345030027303330300030096096303330300096096030030096096300303306096342303291300285324333309096126291342309345030096096096096315306096291342309345273144279138348333285345096183183096102102177096096342291315345303096102219330336351348096342303339351315342303345096324333309336291348312138102177096096303330300177096096336291348312096183096291342309345273144279030027315306096210315324303138306315324303189120249267249252207231138324333309300315342129102141102129336291348312123096183183096306291324345303096291330300096210315324303138306315324303189120249267249252207231138324333309300315342129102141102129336291348312129102138324333309102123177096096336291348312096183096249267249252207231138324333309300315342129102141102129336291348312129102138324333309102030027303324345315306096210315324303138306315324303189120249267249252207231138324333309300315342129102141102129336291348312123177096096336291348312096183096249267249252207231138324333309300315342129102141102129336291348312030027303330300030027315306096291342309345273147279138315345285291189120219330348303309303342123177096096315330300303360096183096291342309345273147279138348333285315030027303324345315306096291342309345273147279138315345285291189120246291330309303123177096315330300303360096183096291342309345273147279030027303324345303177096315330300303360096183096348342351303030027303330300030027315306096210315324303138306315324303189120336291348312123030027096096306096183096210315324303138333336303330120336291348312132102342102123177096300291348096183096306138342303291300177096306138297324333345303030027096096330300291348096183096300291348138345336324315348120102276330102123030027096096315306096315330300303360096183183096348342351303177096096342303348351342330096330300291348030027096096303324345303177096096342303348351342330096330300291348273315330300303360279030027096096303330300030027303324345303177096096342303348351342330096102234333096345351297312096306315324303174096102129291342309345273144279138348333285345030096096096096303330300030096096303330300096096030030096096300303306096297324303291330285324333309345030096096096096306315324303345096183096273279177096297324303291330303300096183096273279030027297333330348183204315342138303330348342315303345120249267249252207231138324333309300315342123177096096297333330348138300303324303348303120102138102123177096096297333330348138300303324303348303120102138138102123030096096096096315306096297333330348138324303330309348312096183183096144096177096096342303348351342330096330315324030027303324345303177096096297333330348138303291297312096369096372297372096315306096297138300333357330297291345303138303330300285357315348312189120102138324333309102123096333342096297138300333357330297291345303138303330300285357315348312189120102138348360348102123177096315306096210315324303138345315366303189120249267249252207231138324333309300315342129102141102129297123186144177096096306315324303345096180180096297177096096303330300177096096303330300375030027303330300030027315306096306315324303345138324303330309348312096183183096144096177096096342303348351342330096102252312303342303096357303342303096330333096324333309345096348333096297324303291330102177096096303330300030027306315324303345138303291297312096300333096372306372030027096096336096183096249267249252207231138324333309300315342129102141102129306030027096096294303309315330030027096096096096306183210315324303138333336303330120336132102342102123177096300291348183306138342303291300177306138297324333345303030027027315306096300291348138345336324315348120102276330102123138324303330309348312096186096147144144144030027027096096249267249252207231138357342315348303324333309096102201324303291330315330309096324333309096306315324303174096102129336138345336324315348120102141102123273135147279030027027096096330300291348096183096273279030027027096096300183300291348138345336324315348120102276330102123273135171171171138138135147279030027027096096210315324303138300303324303348303120336123030027027096096306183210315324303138333336303330120336132102357102123177096096306138357342315348303120330300291348123177096096306138297324333345303030027027096096249267249252207231138357342315348303324333309096102201324303291330303300096324333309174096102129336138345336324315348120102141102123273135147279030027027096096297324303291330303300096180180096336138345336324315348120102141102123273135147279030027027303330300030027096096342303345297351303177096096249267249252207231138303342342333342324333309096102228333309096297324303291330315330309096357291345096351330291294324303096348333096333336303330096306315324303174096102129306138348333285345030027096096303330300030027303330300030027249267249252207231138357342315348303324333309096102228333309096297324303291330303342096297324303291330303300096102129297324303291330303300138324303330309348312138348333285345129102096324333309345138096102129297324303291330303300138348333285345030027315306096297324303291330303300138324303330309348312096183183096144096177096342303348351342330096102234333096324333309345096357303342303096297324303291330303300138102030027303324345303177096096342303348351342330096297324303291330303300138324303330309348312138348333285345129102096324333309345096357303342303096297324303291330303300138096120102129297324303291330303300138348333285345129102123102030027303330300030096096303330300030096096096096030096096300303306096327303291345351342303285324333309345030027306315324303345096183096273279177096342303348096183096273279030027297333330348183204315342138303330348342315303345120249267249252207231138324333309300315342123177096096297333330348138300303324303348303120102138102123177096096297333330348138300303324303348303120102138138102123030096096096096315306096297333330348138324303330309348312096183183096144096177096096342303348351342330096330315324030027303324345303177096096297333330348138303291297312096369096372297372096315306096297138300333357330297291345303138303330300285357315348312189120102138324333309102123096333342096297138300333357330297291345303138303330300285357315348312189120102138348360348102123177096096306315324303345096180180096297177096096303330300375030027303330300030027315306096306315324303345138324303330309348312096183183096144096177096096342303348351342330096273279030027303324345303105105030027096096306315324303345138303291297312096300333096372306372030027096096096096306315324303183210315324303138333336303330120249267249252207231138324333309300315342129102141102129306138348333285345132102342102123177096300291348183306315324303138342303291300138348333285345177096096306315324303138297324333345303030027027324315330303345183300291348138345336324315348120102276330102123138324303330309348312030027027342303348096180180096273306138348333285345132102228315330303345174096102129324315330303345138348333285345132102249315366303174096102129210315324303138345315366303189120249267249252207231138324333309300315342129102141102129306138348333285345123138348333285345279030027096096303330300030027096096342303348351342330096342303348030027303330300030096096303330300030096096030096096300303306096303327336348363285324333309120336291348312123030096096096096315306096336291348312138348333285345096183183096102102177096096342291315345303096102219330336351348096342303339351315342303345096324333309336291348312138102177096096303330300030027336291348312096183096291342309345273144279030027315306096210315324303138306315324303189120249267249252207231138324333309300315342129102141102129336291348312123096183183096306291324345303096291330300096210315324303138306315324303189120249267249252207231138324333309300315342129102141102129336291348312129102138324333309102123030027096096336291348312096183096249267249252207231138324333309300315342129102141102129336291348312129102138324333309102030027096096336351348345096102210315360303300096336291348312174096102129096336291348312138348333285345030027303324345315306096210315324303138306315324303189120249267249252207231138324333309300315342129102141102129336291348312123030027096096336291348312096183096249267249252207231138324333309300315342129102141102129336291348312030027303324345303177096096342291315345303096102255330291294324303096348333096324333297291348303096324333309138102030027303330300030096096096096306096183096210315324303138333336303330120336291348312132102357102123177096306138357342315348303120252315327303138330333357138348333285345129102096228333309096357291345096303327336348315303300138102123177306138297324333345303030096096096096342303348351342330096348342351303030096096303330300030030096096105105096249216255252204237261234096141096246207249252195246252096231207252216237204249096096096030096096300303306096345312351348300333357330285345303339351303330297303096126291342309345096096105105096351345303342096291330300096291336336096342303339351303345348345096309333096348312342333351309312096312303342303132096351345303096291342309096348342351303096348333096345321315336096297333351330348300333357330030096096096096315306096192345312351348300333357330096099183096306291324345303177096096342303348351342330096306291324345303177096096303330300096177096096192345312351348300333357330096183096348342351303030027249267249252207231138357342315348303324333309120102246351294315330138345312351348300333357330285345303339351303330297303174096249363345348303327096345312351348300333357330096336342333297303345345096312291345096294303309351330138102123030030096096096096345312351348300333357330345297342315336348183306291324345303030096096096096315306096192297333330306315309273147159279273147279096183183096348342351303177096096345312351348300333357330345297342315336348096183096348342351303096177096096303330300030027315306096345312351348300333357330345297342315336348096183183096348342351303096291330300096210315324303138306315324303189120108300291348291300315342129102141345297342315336348345141345312351348300333357330138342294102123030027096096294303309315330177096096249267249252207231138315330345348291330297303285303354291324120210315324303138342303291300120108300291348291300315342129102141345297342315336348345141345312351348300333357330138342294102123123030027096096342303345297351303096183186096303096177096249267249252207231138303342342333342324333309120102246351294315330138345312351348300333357330285345303339351303330297303174096249312351348300333357330096345297342315336348096336342333300351297303300096291330300096303360297303336348315333330174096102129303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123123030027096096303330300030027303330300030096096096096105297333351330348300333357330096348312342303291300030027351330324303345345096291342309345273144279096183183096348342351303096177096252312342303291300138330303357096369192345312351348300333357330096183096153144177096153144138348315327303345369096345324303303336096147138144177096294303309315330177096192345312351348300333357330096135183096147096177342303345297351303177177303330300096375177096375096177096096303330300030027345303324306138345291354303285297333330306315309030027345303324306138345291354303285297291297312303030096096096096315306096192291336336345138324303330309348312096186096144030027096096192291336336345138303291297312096369096372291372096030027096096096096315306096291273153279096183183096330315324096177096096330303360348096177096096303330300030027027315306096291273153279138327303348312333300345138315330297324351300303189120174345312351348300333357330285294303312291354315333342123030096096096096096096096096096096294303309315330096177096096291273153279138345312351348300333357330285294303312291354315333342030027027096096342303345297351303096183186096303096177096096249267249252207231138303342342333342324333309120102246351294315330138345312351348300333357330285345303339351303330297303174096102096129096291273144279096129096102096345312351348300333357330285294303312291354315333342096336342333300351297303300096291330096303360297303336348315333330174096102096129096303138348333285345096129096102276330102096129096303138294291297321348342291297303138318333315330120102276330102123123030027027096096303330300030096096096096096096096096303330300030027096096375096030027096096249267249252207231138357342315348303324333309120102246351294315330138345312351348300333357330285345339351303330297303174096249348333336336303300096291336336345138102123030027303330300030027315306096249267249252207231138300291303327333330300099183096330315324030027096096249267249252207231138300291303327333330300138345312351348300333357330030027096096249267249252207231138357342315348303324333309120102246351294315330138345312351348300333357330285345303339351303330297303174096249348333336336303300096300291303327333330300138102123030027303330300027096096030027294303309315330177096096210315324303138300303324303348303120192300291348291300315342129102141345363345141315330345348291330297303141102129219234249252195234201207138348333285345129102138300291348102123177096096342303345297351303177096096303330300030027249267249252207231138357342315348303324333309120102246351294315330138345312351348300333357330285345303339351303330297303174096249363345348303327096315345096300333357330138102123030027105105357291315348096306333342096297333351330348300333357330096348312303330096297291324324096303360315348030027315306096291342309345273144279096099183096348342351303096177096252312342303291300138330303357096369324333333336096300333096177096345324303303336096147138144096177096315306096192345312351348300333357330096180096147096177096303360315348096177096096303330300096177096096303330300096375030027303324345303096177096096303360315348030027303330300030096096096096342303348351342330096348342351303030096096303330300030096096030096096300303306096345312351348300333357330096126291342309345096105105096345363345348303327096342303339351303345348345096309333096348312342333351309312096312303342303132096348312315345096324315330321345096348333096345303339351303330297303096312333357303354303342096291342309345273144279096294363336291345345096336342333327336348096177096291342309345273147279096294363336291345345096297333351330348300333357330030096096096096315306096192345312351348300333357330096099183096306291324345303177096096342303348351342330096306291324345303177096096303330300030096096096096336342333297303303300183306291324345303030027315306096291342309345273144279096183183096348342351303177096096336342333297303303300183348342351303030096096096096303324345303177096096336351348345096102276330195342303096363333351096345351342303096363333351096357291330348096348333096345312351348300333357330096246351294315330189096267141234102030027096096315330336183309303348345138297312333327336273144279138300333357330297291345303030027096096315306096315330336183183102363102177336342333297303303300183348342351303177303330300030027303330300030027315306096336342333297303303300030027096096315306096291342309345273144279096183183096348342351303030027096096096096249267249252207231138357342315348303324333309120102246351294315330138345312351348300333357330174096249363345348303327096249312351348300333357330096210102123030096096096096096096096096249267249252207231138345312351348300333357330285345303339351303330297303120291342309345273147279123030027096096303324345303030027096096096096249267249252207231138357342315348303324333309120102246351294315330138345312351348300333357330174096249363345348303327096345312351348300333357330096345303339351303330297303096312291345096294303303330096342303339351303345348303300138102123030096096096096096096096096249267249252207231138345312351348300333357330285345303339351303330297303120291342309345273147279123030027096096303330300030027096096342303348351342330096348342351303030027303324345303030027096096342303348351342330096306291324345303030027303330300030096096303330300030096096030096096300303306096342303345348291342348096126291342309345030096096096096336342333297303303300183306291324345303030027315306096291342309345273144279096183183096348342351303177096096336342333297303303300183348342351303030096096096096303324345303177096096336351348345096102276330195342303096363333351096345351342303096363333351096357291330348096348333096342303345348291342348096246351294315330189096120267141234123102030027096096315330336183309303348345138297312333327336273144279138300333357330297291345303030027096096315306096315330336183183102363102177336342333297303303300183348342351303177303330300030027303330300030027315306096336342333297303303300183183306291324345303177096096342303348351342330096306291324345303177096096303330300030027249267249252207231138357342315348303324333309120102246351294315330138342303345348291342348174096240342303336291342315330309096348333096342303345348291342348096246351294315330132096249363345348303327096345312351348300333357330096336342333297303345345096312291345096294303309351330138096102123030027249267249252207231138312333345348138324291351330297312285330303357120192312333327303300315342129102141324291351330297312138342294102123030096096096096249267249252207231138345312351348300333357330285345303339351303330297303120348342351303123030027342303348351342330096348342351303030096096303330300030096096030096096300303306096312291342300285342303345348291342348096126291342309345030096096096096336342333297303303300183306291324345303030027315306096291342309345273144279138348333285345273144279183183102210102177096096336342333297303303300183348342351303030096096096096303324345303177096096336351348345096102276330195342303096363333351096345351342303096363333351096357291330348096348333096096216195246204096246207249252195246252096246351294315330189096267333351096327291363096324333345303096300291348291138096120267141234123102030027096096315330336183309303348345138297312333327336273144279138300333357330297291345303030027096096315306096315330336183183102363102177336342333297303303300183348342351303177303330300030027303330300030027315306096336342333297303303300183183306291324345303177096096342303348351342330096306291324345303177096096303330300030027294303309315330177210315324303138300303324303348303120192300291348291300315342129102141345363345141315330345348291330297303141102129219234249252195234201207138348333285345129102138300291348102123177096096342303345297351303177177096096303330300030027249267249252207231138357342315348303324333309120102246351294315330138312291342300285342303345348291342348174096216195246204096246207249252195246252132096291294333351348096348333096342303345348291342348138102123030027315306096291342309345273144279138348333285345099183102210102177096096345324303303336096147138144177303330300030027249267249252207231138312333345348138324291351330297312285330303357120192312333327303300315342129102141324291351330297312138342294102123030027315306096291342309345273144279138348333285345099183102210102177096096345324303303336096144138147177096096303330300030027303360315348030096096303330300030096096030096096300303306096312291342300285345312351348300333357330096126291342309345030096096096096336342333297303303300183306291324345303030027315306096291342309345273144279096183183096348342351303096177096096336342333297303303300183348342351303030096096096096303324345303177096096336351348345096102276330195342303096363333351096345351342303096363333351096357291330348096348333096216195246204096249216255252204237261234096246351294315330189096267333351096327291363096324333345303096300291348291138096120267141234123102030027096096315330336183309303348345138297312333327336273144279138300333357330297291345303030027096096315306096315330336183183102363102177336342333297303303300183348342351303177303330300030027303330300030027315306096336342333297303303300030027096096294303309315330177096096210315324303138300303324303348303120192300291348291300315342129102141345363345141315330345348291330297303141102129219234249252195234201207138348333285345129102138300291348102123177096096342303345297351303177177096096303330300030027096096249267249252207231138357342315348303324333309120102246351294315330138312291342300285345312351348300333357330174096216195246204096249216255252204237261234132096291294333351348096348333096345312351348300333357330138102123030027096096303360315348030027303330300030096096303330300030096096030096096030096096030096096030096096030096096030096096030096096030096096105105096201237234210219213096231207252216237204249030096096300303306096297333330306315309096126291342309345030096096096096333324300285297333330306315309183303354291324120192297333330306315309138348333285345123096096105105138138138138318351345348138138138261216267189099096327291363294303096348333096297291348297312096297333342342351336348315333330345189030027030096096096096315306096291342309345138324303330309348312183183144096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096105105096246207252255246234030027096297306309183273279177192297333330306315309285330291327303345138303291297312096369372297372096297306309096180180096273297132192297333330306315309273192297333330306315309285330291327303345138315330300303360120297123279279375030027096096342303348351342330096297306309030027303324345315306096291342309345273144279138315345285291189120219330348303309303342123096291330300096291342309345138324303330309348312183183147096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096105105096246207252255246234096273219330348279030027096096342303348351342330096192297333330306315309273291342309345273144279138348333285315279030027303324345315306096291342309345273144279138315345285291189120219330348303309303342123096291330300096291342309345138324303330309348312183183150096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096105105096249207252096273219330348279183030027096096192297333330306315309273291342309345273144279279183291342309345273147279030027303324345315306096291342309345273144279138315345285291189120249348342315330309123096333342096291342309345273144279138315345285291189120249363327294333324123096291330300096192297333330306315309285330291327303345138315330297324351300303189120291342309345273144279138348333285345123096291330300096291342309345138324303330309348312183183147096096096105105096246207252255246234096273249348342279030027096096342303348351342330096192297333330306315309273192297333330306315309285330291327303345138315330300303360120291342309345273144279138348333285345123279030027303324345315306096291342309345273144279138315345285291189120249348342315330309123096333342096291342309345273144279138315345285291189120249363327294333324123096291330300096192297333330306315309285330291327303345138315330297324351300303189120291342309345273144279138348333285345123096291330300096291342309345138324303330309348312183183150096096096105105030027096096192297333330306315309273192297333330306315309285330291327303345138315330300303360120291342309345273144279138348333285345123279183291342309345273147279030027303324345303177342291315345303096102219330354291324315300096291342309351327303330348138102030027303330300030027030096096096096105105096300303348303297348096297312291330309303345096291330300096336303342306333342327096291351348333096342303345336333330345303096348333096297333330306315309096297312291330309303345030027297315096183096273279177096315096183096144030027333324300285297333330306315309138303291297312096369096372333297372096315306096333297138348333285345096099183096192297333330306315309273315279138348333285345177096096297315096180180096315177096096303330300177096096315129183147096375030027315306096297315138315330297324351300303189120144123030027303330300030027315306096297315138315330297324351300303189120147123030027303330300030027315306096297315138315330297324351300303189120150123030027303330300030027315306096297315138315330297324351300303189120153123030027303330300030027315306096297315138315330297324351300303189120156123096096105105096297333330306315309096156096300303294351309030027096096315306096192297333330306315309273156279096183183096348342351303177096096108300303294351309096183096348342351303177096096303324345303177096096108300303294351309096183096306291324345303177096096303330300030096096096096096096315306096192297333330306315309273156279096183183096348342351303096291330300096210315324303138306315324303189120192297306309300315342129102141300303294351309138306324291309102123096183183096306291324345303177096096306183210315324303138333336303330120192297306309300315342129102141300303294351309138306324291309102132102357102123177306138297324333345303177096096303330300030096096096096096096315306096192297333330306315309273156279096099183096348342351303096291330300096210315324303138306315324303189120192297306309300315342129102141300303294351309138306324291309102123096183183096348342351303177096096210315324303138300303324303348303120192297306309300315342129102141300303294351309138306324291309102123177096096303330300030096096096096096096315306096192297333330306315309273156279096099183096348342351303096291330300096210315324303138306315324303189120192312333327303300315342129102141300303294351309138306324291309102123096183183096348342351303177096096210315324303138300303324303348303120192312333327303300315342129102141300303294351309138306324291309102123177096096303330300096096105105096294303297291351345303096294333333348096291324345333096297312303297321345096312303342303030027096096336351348345096102204207198255213096306324291309096357291345096297312291330309303300174096102129108300303294351309138348333285345030027303330300030027342303348351342330096348342351303030096096303330300030096096096030096096300303306096324333291300285297333330306315309096126291342309345096105105096363333351096297291330096336291345345096291096306315324303336291348312096348333096324333291300096297333330306315309096306342333327096333342096324303291354303096294324291330321096348333096324333291300096300303306291351324348030096096096096306315324303183306291324345303030096096096096315306096291342309345138324303330309348312183183144096291330300096210315324303138306315324303189120192297306309300315342129102141297333330306315309138297306309102123030027096096306315324303183192297306309300315342129102141297333330306315309138297306309102030096096096096303324345315306096210315324303138306315324303189120192297306309300315342129102141102129291342309345273144279138348333285345123096291330300096291342309345273144279138348333285345273135156138138135147279138348333285345138300333357330297291345303183183102138297306309102030096096096096096096306315324303183192297306309300315342129102141102129291342309345273144279138348333285345030096096096096303324345303030096096096096096096342303348351342330096306291324345303030096096096096303330300030027306183210315324303138333336303330120306315324303138348333285345132102342102123177297306309183306138342303291300177306138297324333345303030027294303309315330177297306309183303354291324120297306309123177192297333330306315309183297306309177192324333291300303300285297333330306315309183306315324303138348333285345177249267249252207231138357342315348303324333309120102228333291300303300096297333330306315309174096102129306315324303138348333285345123030027096096315306096192297333330306315309273156279096183183096306291324345303096291330300096210315324303138306315324303189120192297306309300315342129102141300303294351309138306324291309102123096183183096348342351303030027096096096096192297333330306315309273156279096183096348342351303030027096096303324345315306096192297333330306315309273156279096183183096348342351303096291330300096108300303294351309096099183096348342351303030027096096096096108300303294351309096183096348342351303030027096096303330300030027096096315306096108300303294351309096177096336351348345096102201333330306315309096324333291300303300174096102129306315324303138348333285345138345336324315348120102141102123273135147279096177096096303330300030027096096342303348351342330096348342351303030027342303345297351303096105105096201237234210219213096204195252195096201237246246255240252207204027096096096030027096096345303324306138303342342333342324333309120102249363345348303327096297333330306315309096324333291300096306291315324303300096300351303096348333096297333342342351336348315333330138102123030027096096342303348351342330096306291324345303096030096096096096303330300027030096096303330300030096096030096096300303306096345291354303285297333330306315309096126291342309345096096096105105096363333351096297291330096336291345345096291096330291327303096348333096345291354303096297333330306315309096291345096333342096294324291330321096306333342096300303306291351324348030096096096096315306096291342309345138324303330309348312183183144030027096096306183210315324303138333336303330120192297306309300315342129102141297333330306315309138297306309102132102357102123177306138357342315348303120192297333330306315309138348333285345123177306138297324333345303030027096096345303324306138357342315348303324333309120102249363345348303327096297333330306315309096345291354303300138102123030027303324345315306096291342309345273144279138348333285345138324303330309348312186144030027096096315306096291342309345273144279138315345285291189120249348342315330309123030027096096096096294303309315330030027096096096096096096306183210315324303138333336303330120192297306309300315342129102141102129291342309345273144279138348333285345129102138297306309102132102357102123177306138357342315348303120192297333330306315309138348333285345123177306138297324333345303030027096096096096096096345303324306138357342315348303324333309120102249363345348303327096297333330306315309096345291354303300096291345096117102129291342309345273144279138348333285345129102117138297306309138102123030027027096096105105297333330348315330351303030027096096096096342303345297351303030027096096096096096096342303348351342330096306291324345303030027096096096096303330300030027096096303324345315306096291342309345273144279138315345285291189120195342342291363123030027096096096096294303309315330030027027096096306183210315324303138333336303330120192297306309300315342129102141102129291342309345273147279138348333285345132102357102123177096096306138357342315348303120291342309345273144279138348333285345123030027027096096105105297333330348315330351303030027027342303345297351303030027027096096342303348351342330096306291324345303030027096096096096303330300030027096096303324345303177096096342291315345303096102219330354291324315300096291342309351327303330348345138102030027096096303330300030027303324345303030027096096342303348351342330096306291324345303030027303330300030027105105297291330096342303291297312096312303342303096351330324303345345096306291324345303345096291294333354303096291342303096291354333315300303300030096096096096315306096192297333330306315309273156279096183183096348342351303096291330300096210315324303138306315324303189120192297306309300315342129102141300303294351309138306324291309102123096183183096306291324345303030027096096108300303294351309096183096348342351303030027096096306096183096210315324303138333336303330120192297306309300315342129102141300303294351309138306324291309102132102357102123096177096096306138297324333345303030027303324345315306096192297333330306315309273156279096183183096306291324345303096291330300096210315324303138306315324303189120192297306309300315342129102141300303294351309138306324291309102123096183183096348342351303030027096096294303309315330096177096096210315324303138300303324303348303120192297306309300315342129102141300303294351309138306324291309102123096177096096108300303294351309096183096306291324345303096177096096303330300030027303330300030027342303348351342330096348342351303030096096303330300030096096030096096300303306096342303336291315342285297333330306315309030096096096096345303324306138357342315348303324333309120102249363345348303327096201333330306315309096300291348291096315345096294303315330309096342303336291315342303300138102123030027294303309315330030027096096306183210315324303138333336303330120249267249252207231138297306309300315342129102141297333330306315309138297306309102132102342102123177096300291348183306138342303291300177096096306138297324333345303030027096096336096183096249267249252207231138300291348291300315342129102141294291297321351336345141297333330306315309135297333342342351336348303300285294291297321351336135102129252315327303138330333357138348333285345138345336324315348120102096102123273144138138147279138318333315330120102138102123138345336324315348120102174102123138318333315330120102138102123138345336324315348120102135102123138318333315330120102138102123129102138297306309138300291348102030027096096306183210315324303138333336303330120336132102357102123177096306138357342315348303120300291348123177096096306138297324333345303030027096096249267249252207231138357342315348303324333309120102237324300096297333330306315309096300291348291096357291345096294291297321303300351336096348333174096102129336138348333285345123030027342303345297351303177096096249267249252207231138303342342333342324333309120102201333330306315309096342303336291315342096306291315324303300096348333096294291297321351336096333324300096297333330306315309096300291348291138102123030027303330300030096096096096192297333330306315309183192300303306291351324348285297333330306315309096177096096192324333291300303300285297333330306315309096183096102297333330306315309138297306309102030096096096096345303324306138345291354303285297333330306315309027096030096096303330300030096096030096096300303306096342303291300285297333330306315309096126291342309345030096096096096315306096291342309345273144279138348333285345096183183096102102177096096342291315345303096102219330336351348096342303339351315342303345096249348342315330309102177096096303324345303177096096336291348312096183096291342309345273144279138348333285345177096096303330300030096096096096315306096210315324303138306315324303189120336291348312123177096096336291348312096183096336291348312030027303324345315306096210315324303138306315324303189120249267249252207231138297306309300315342129102141102129336291348312123177096096336291348312096183096249267249252207231138297306309300315342129102141102129336291348312030027303324345315306096210315324303138306315324303189120249267249252207231138297306309300315342129102141102129336291348312129102138297306309102123177096096336291348312096183096249267249252207231138297306309300315342129102141102129336291348312129102138297306309102030027303324345315306096210315324303138306315324303189120249267249252207231138297306309300315342129102141102129336291348312129102138297333330306315309102123177096096336291348312096183096249267249252207231138297306309300315342129102141102129336291348312129102138297333330306315309102030027303324345303177096096342291315345303096102234333096345351297312096306315324303174096102129336291348312030027303330300030027294303309315330177096096306096183096210315324303138333336303330120336291348312132102342102123177096096300291348183306138342303291300030027342303345297351303177096096342291315345303096102210315324303096342303291300096306291315324303300174096102129096336291348312138348333285345030027303330300030096096096096315306096300291348138324303330309348312186144030027096096294303309315330177096300291348291096183096303354291324120300291348123030027096096096096315306096291342309345138324303330309348312096183183096147177096096342303348351342330096300291348291030027027303324345315306096291342309345138324303330309348312096183183096150096291330300096291342309345273147279138315345285291189120219330348303309303342123030027027096096342303348351342330096300291348291273291342309345273147279279030027027303324345315306096291342309345138324303330309348312096183183096150096291330300096291342309345273147279138315345285291189120246291330309303123030027027096096342303348351342330096300291348291273291342309345273147279279030027027303324345303177096096342291315345303096102219330354291324315300096291342309351303327303330348132096345303297333330300096291342309351303327303330348096345312333351324300096294303096219330348303309303342096333342096246291330309303138102030027027303330300030027096096342303345297351303177096096342291315345303096102201333330306315309096303354291324096306291315324303300174096102129336291348312138348333285345030027096096303330300030027303324345303177096096342291315345303096102201333330306315309096306315324303096357291345096303327336348363174096102129336291348312138348333285345030027303330300030096096303330300030096096030096096300303306096357342315348303285297333330306315309096126291342309345030096096096096315306096291342309345273144279138348333285345096183183096102102177096096342291315345303096102219330336351348096342303339351315342303345096249348342315330309102177096096303324345303177096096336291348312096183096291342309345273144279138348333285345177096096303330300030096096096096315306096210315324303138306315324303189120336291348312123177096096336291348312096183096336291348312030027303324345315306096210315324303138306315324303189120249267249252207231138297306309300315342129102141102129336291348312123177096096336291348312096183096249267249252207231138297306309300315342129102141102129336291348312030027303324345315306096210315324303138306315324303189120249267249252207231138297306309300315342129102141102129336291348312129102138297306309102123177096096336291348312096183096249267249252207231138297306309300315342129102141102129336291348312129102138297306309102030027303324345315306096210315324303138306315324303189120249267249252207231138297306309300315342129102141102129336291348312129102138297333330306315309102123177096096336291348312096183096249267249252207231138297306309300315342129102141102129336291348312129102138297333330306315309102030027303324345303177096096342291315345303096102234333096345351297312096306315324303174096102129336291348312030027303330300030027315306096291342309345273147279138315345285291189120219330348303309303342123177096096336333345096183096291342309345273147279030027303324345315306096291342309345273147279138315345285291189120246291330309303123177096096336333345096183096291342309345273147279030027303324345303177096342291315345303096102219330354291324315300096315330336351348132096345303297333330300096291342309351303327303330348096342303339351315342303345096219330348303309303342096333342096246291330309303138102030027303330300030027315306096291342309345138324303330309348312096183183096153177096096354291324351303096183096291342309345273150279030027303324345303177096096342291315345303096102207342342333342132096348312315342300096291342309351327303330348096315345096342303339351315342303300138102030027303330300030096096096096315306096210315324303138306315324303189120336291348312123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303174096102129336291348312138348333285345030027303330300030027294303309315330177096096306096183096210315324303138333336303330120336291348312132102342102123177096096300291348183306138342303291300030027342303345297351303177096096342291315345303096102210315324303096342303291300096306291315324303300174096102129096336291348312138348333285345030027303330300030027294303309315330177096096300291348291183303354291324120300291348123030027342303345297351303177096096342291315345303096102210291315324303300096348333096342303291300096297333330306315309174096102129336291348312138348333285345030027303330300030027300291348291273336333345279183354291324351303030027294303309315330177096096306096183096210315324303138333336303330120336291348312132102357102123177096096306138357342315348303120300291348291138348333285345123177096096306138297324333345303177096096342303348351342330096348342351303030027342303345297351303177096096342291315345303096102210315324303096357342315348303096306291315324303300174096102129336291348312138348333285345030027303330300030096096303330300030096096030096096300303306096342303327333354303285291324348297333330306315309030096096096096315306096345303324306138291324348297333330306315309189030027096096294303309315330177096096210315324303138300303324303348303120192297306309300315342129102141291324348297333330306315309138297306309102123177096096342303348351342330096348342351303030027096096342303345297351303177096096345303324306138303342342333342324333309120102210291315324303300096348333096300303324303348303096291324348297333330306315309096306315324303138102123177096096342303348351342330096306291324345303030027096096303330300030027303324345303177096096342303348351342330096306291324345303030027303330300030096096303330300030096096030096096300303306096297342303291348303285336342303297333330306315309096126291342309345096096096096096096105105096297333330306315309132096315330348303309303342030096096096096315306096291342309345273144279138315345285291189120195342342291363123030027096096315306096291342309345273144279138324303330309348312096099183096192297333330306315309138324303330309348312030027096096096096342291315345303096102213315354303330096297333330306315309096291342342291363096300333303345096330333348096327291348297312096345363345348303327096297333330306315309096291342342291363096324303330309348312138102030027096096303330300030027303324345303177096342291315345303096102210315342345348096291342309351303327303330348096327351345348096294303096297333330306315309096291342342291363138102030027303330300030027315306096291342309345138324303330309348312183183147030027096096297306309345183273279030096096096096096096204315342138303330348342315303345120192297306309300315342123273150138138135147279138303291297312096369096372315372096315306096315138348333285345138300333357330297291345303273144138138168279183183102336342303297333330306315309102177096096297306309345096180180096315177096096303330300096375030096096096096096096315183297306309345138324303330309348312030096096096096303324345303030027096096315306096291342309345273147279138315345285291189120219330348303309303342123096183183096306291324345303030027096096096096342291315345303096102249303297333330300096291342309351303327303330348096315345096330333348096291330096315330348303309303342138102030027096096303324345303030027096096096096315183291342309345273147279138348333285315030027096096303330300030027303330300030027336291348312183192297306309300315342129102141336342303297333330306315309102129315138348333285345129102138297306309102030027306183210315324303138333336303330120336291348312132102357102123177096096306138357342315348303120291342309345273144279138348333285345123177096096306138297324333345303030096096096096342303348351342330096315030096096303330300030030030096096300303306096324333291300285297291297312303030096096303330300030030096096300303306096345291354303285297291297312303030096096303330300030030096096300303306096342303336291315342285297291297312303030030096096303330300096096030030096096105105096228237195204141246255234096231207252216237204249030096096030096096105105096306315309351342303096333351348096357312291348096348312303096306351297321096357303096357291330348096345312333342348297351348345096348333096294303132096315300303291324324363096297327300141312333345348096345297342315336348096306315324303345030096096300303306096345312333342348297351348120345348342123096096105105096324333291300096342351294363096306315324303345096315330096291096330303357096342351294363096315330348303342336342303348303342096357315330300333357030096096096096105096315306096345348342273135153138138135147279138348333285345138300333357330297291345303099183102138342294102177345348342183345348342138348333285345129102138342294102177303330300030096096096096105096315306096210315324303138303360315345348189120192312333327303300315342129102141345312333342348297351348345141102129345348342138348333285345129102138342294102123030027096096105096333300315342183204315342138309303348357300030027096096105096204315342138297312300315342120192312333327303300315342129102141345312333342348297351348345102123030027096096105096345363345348303327120102345348291342348096102129345348342138348333285345129102138342294102123030027096096105096204315342138297312300315342120333300315342123030027096096105096342303348351342330096348342351303096096030027105096303324345303177342303348351342330096306291324345303030027105096303330300030096096303330300030096096030096096030096096105105096324333291300096297324291345345303345096030096096300303306096324333291300285297324291345345300315342096126291342309345030096096096096324333291300285297324291345345303345096183096273279096177096324333291300303300285297324291345345303345096183096273279030027315306096291342309345138324303330309348312096183183096144030027096096204315342138303330348342315303345120192297324291345345300315342123138303291297312096300333096372306372030027096096096096315306096306138348333285345096183183096102138102096333342096306138348333285345096183183096102138138102096177096096330303360348096177096096303330300030027027315306096210315324303138306315324303189120192297324291345345300315342096129096102141102096129096306138348333285345123096291330300096306138348333285345138300333357330297291345303273135153138138135147279096183183096102138342294102096177096096324333291300285297324291345345303345096180180096306138348333285345096177096096303330300030027096096303330300030027303324345303096177096096324333291300285297324291345345303345096183096291342309345273144279030027303330300030096096096096315306096324333291300285297324291345345303345138324303330309348312096183183096144030027096096249267249252207231138357342315348303324333309120102246351294315330138324333291300285297324291345345300315342174096234333096297324291345345303345096357303342303096306333351330300096348333096294303096324333291300291294324303138102123030027096096342303348351342330096144030027303330300030096096096096324333291300285297324291345345303345138303291297312096300333096372297372030096096096096096096294303309315330030027096096096096294303309315330096177096096306096183096210315324303138333336303330120192297324291345345300315342096129096102141102096129096297138348333285345132096102342102123096177096096345297342315336348096183096306138342303291300096177096306138297324333345303030027027342303345297351303096177096096342291315345303096102210291315324303300096348333096342303291300096306315324303138102030027027303330300030027096096096096231195219234138315330345348291330297303285303354291324120345297342315336348123096177096096192324333291300303300285297324291345345303345096180180096297138348333285345096177096324333291300303300285297324291345345303345096180180096297138348333285345096096030027027249267249252207231138357342315348303324333309120102246351294315330138324333291300285297324291345345300315342174096228333291300303300096297324291345345096306315324303174096102096129096297138348333285345123030027096096342303345297351303096183186096303030027096096096096249267249252207231138303342342333342324333309120102246351294315330138324333291300285297324291345345300315342174096201324291345345096306315324303096336342333300351297303300096291330096303360297303336348315333330174096102096129096297138348333285345096129096102132096207342342333342174096102096129096303138348333285345096129096102276330102096129096303138294291297321348342291297303138318333315330120102276330102123123030027096096303330300030096096096096303330300030027315306096324333291300303300285297324291345345303345138324303330309348312096186096144096177096315306096108300303294351309096177096096336351348345096102228333291300303300096297324291345345303345174096102096129096324333291300303300285297324291345345303345138348333285345096177096096303330300096177096096303330300030027342303348351342330096324333291300303300285297324291345345303345030096096303330300030096096291324315291345096174324333291300285297324291345345303345096174324333291300285297324291345345300315342030030030096096105105096330333348303174096348312303096345297342315336348096297291330096345303303096315330345348291330297303096354291342315291294324303345096324315321303096291342309345096291330300096291291342309345030096096105105096357303096291300300303300096333336348315333330345096306333342096315330348303342330291324141303360348303342330291324096291330300096336291345345315330309096291342309345132096306315330330291324363096348312303096330291327303096096345312333351324300096312291354303096291330096303360348303330345315333330096306333342096303360348303342330291324096333330324363096345297342315336348345030096096300303306096342351330345096126291342309345096096105105096330291327303132096126291342309345132096303360348303342330291324030096096096096315306096291342309345138324303330309348312096183183096144096333342096291342309345273144279138348333285345138324303330309348312096183183096144177096096342291315345303096102219330354291324315300096291342309351327303330348345132096342303339351315342303345096249348342315330309132096345297342315336348330291327303138102177096096303330300027030096096096096315306096291342309345138324303330309348312096186096147177096096291291342309345096183096291342309345273147279177096096303324345303177096096291291342309345096183096273279177096096303330300030096096096096315306096291342309345138324303330309348312096186096150096291330300096291342309345273150279096183183096348342351303177096096303360348303342330291324096183096348342351303177096096303324345303177096096303360348303342330291324096183096306291324345303177096096303330300030030096096096096345297342315336348330291327303096183096291342309345273144279138348333285345030096096096096345183192300291348291300315342129102141345297342315336348345141102129345297342315336348330291327303138348333285345030027315306096345138348333285345138300333357330297291345303138303330300285357315348312189120102138342294102123096183183096306291324345303177096345183345129102138342294102177303330300030030027105336351348345096102228195255234201216219234213174096102129345138348333285345030027105105096291300318351345348096348312315345096348333096297312303297321096315306096291096345297342315336348096315345096291330096303360348303342330291324096120345297342315336348138303360348138342294123132096306333342096303360348342303330291324096345297342315336348345132096315309330333342303096291342309351303327303330348096354291324096306333342096303360348096351330324303345345096300303294351309096327333300303096315345096333330030030096096096096315306096303360348303342330291324096183183096306291324345303096096096105105096324333291300096345297342315336348096315330096297351342342303330348096342351294363030096096096096096096294303309315330177345348342183210315324303138342303291300120345123030027096096096096345303324306138357342315348303324333309120102246351294315330138342351330345174096342351330330315330309096306315324303174096102129345138345336324315348120102141102123273135147279123030027096096096096294303309315330177096342303345096183096345303324306138315330345348291330297303285303354291324120345348342123096177096096192324333291300303300285306315324303345096180180096345297342315336348330291327303177096096192324333291300303300285345297342315336348345096180180096345297342315336348330291327303030027096096096096342303345297351303096183186096303177096345303324306138357342315348303324333309120102246351294315330138342351330345174096210315324303096336342333300351297303300096291330096303360297303336348315333330174096102129345138345336324315348120102141102123273135147279129102096207342342333342174096102129303138348333285345129102096177096102129303138294291297321348342291297303138318333315330120102276330102123123177096096342303348351342330096303030027096096096096303330300030027096096096096315306096342303345138348333285345096099183096102102177096096342303348351342330096342303345030027096096096096303324345303177096096342303348351342330096348342351303030027096096096096303330300030096096096096096096342303345297351303177096345303324306138357342315348303324333309120102246351294315330138342351330345174096210291315324303300096348333096291297297303345345096306315324303174096102129345138348333285345123177096096342303348351342330096306291324345303030027096096303330300030096096096096303324345303096096105105297342303291348303096291096330303357096357315330300333357345096357315348312096297327300138303360303132096342351330096342351294363096291330300096336291345345096345312333342348297351348096291345096345297342315336348030096096096096096096333300315342183204315342138309303348357300177096096204315342138297312300315342120192312333327303300315342129102141345312333342348297351348345102123030027096096291291342309345096183096291291342309345138318333315330120102096102123030027096096297327300096183096102345348291342348096102129345138348333285345129102096135096102129291291342309345138348333285345030027096096105336351348345096102195198237255252096252237096231195225207096249267249252207231096201195228228174096102129297327300138348333285345030027096096345363345348303327120297327300123030027096096204315342138297312300315342120333300315342123030027096096342303348351342330096348342351303096096030027303330300030096096303330300030027030096096300303306096342351330096126291342309345096105105096291336336330291327303132096273291342309345279030096096096096315306096291342309345138324303330309348312096183183096144096333342096291342309345273144279138348333285345096183183096102102096177096096342291315345303096102246351294315330138342351330174096219330354291324315300096291342309351327303330348345174096120117291336336330291327303117132273117291342309345117279123102096177096096303330300030027315306096249267249252207231138291336336345189120291342309345273144279138348333285345123096183183096306291324345303096177096096249267249252207231138303342342333342324333309120102246351294315330138342351330174096195348348303327336348303300096348333096324333291300096315330354291324315300096291336336174096102129291342309345273144279138348333285345123096177096096342291315345303096102234333096345351297312096291336336174096102129291342309345273144279138348333285345096096177096096303330300030027030027315306096291342309345273144279138348333285345138300333357330297291345303273135153138138135147279096183183096102138342294102096177096096291336336330291327303096183096291342309345273144279138348333285345273144138138135156279030027303324345303096177096096291336336330291327303096183096291342309345273144279096177096096291342309345273144279096183096291342309345273144279096129096102138342294102030027303330300030027030027030027315306096210315324303138306315324303189120192291336336300315342096129096102141102096129096291342309345273144279138348333285345123030096096096096096096348363336303096183096102306315324303102096177096096303330348342363336333315330348096183096192291336336300315342096129096102141102096129096291342309345273144279138348333285345030027303324345315306096210315324303138300315342303297348333342363189120192291336336300315342096129096102141102096129096291342309345273144279138348333285345096129096102141102096129096291342309345273144279138348333285345096129096102138342294102123030027096096348363336303096183096102300315342102096177096303330348342363336333315330348096183096192291336336300315342096129096102141102096129096291342309345273144279138348333285345096129096102141102096129096291342309345273144279138348333285345096129096102138342294102030027303324345303030027096096249267249252207231138303342342333342324333309120102246351294315330138342351330174096195336336096306315324303096300315345291336303291342303300096294303306333342303096315348096297333351324300096294303096324333291300303300174096102129291342309345273144279138348333285345123030027096096342291315345303096102246351294315330138342351330174096252312303096291336336096306315324303096300315345291336303291342303300174096102129291342309345273144279138348333285345030027303330300030027030027192291336336096183096330315324096177096192291336336345312303324324096183096306291324345303096177096096192336333345348285315330315348096183096306291324345303096177096096192345348333336336303300096183096306291324345303030027030027294303309315330096177096096306096183096210315324303138333336303330120303330348342363336333315330348132102342102123096177096096345333351342297303096183096306138342303291300096177096096306138297324333345303030027342303345297351303177096096249267249252207231138303342342333342324333309120102246351294315330138342351330174096210291315324303300096348333096342303291300096291336336096306315324303174096102129303330348342363336333315330348123096177096096342291315345303096102246351294315330138342351330174096210291315324303300096348333096342303291300096291336336096306315324303174096102129303330348342363336333315330348030027303330300030027030027249267249252207231138357342315348303324333309120102246351294315330138342351330174096240342303336291315342315330309096348333096342351330096291336336174096102129291342309345273144279138348333285345123030027030027294303309315330030027096096249267249252207231138315330345348291330297303285303354291324120345333351342297303123030027096096249267249252207231138357342315348303324333309120102246351294315330138342351330174096195336336096342351330096345351297297303345345174096102129291342309345273144279138348333285345123030027096096030027096096192324333291300303300285306315324303345096180180096291342309345273144279138348333285345030027342303345297351303096183186096303030027096096249267249252207231138303342342333342324333309120102246351294315330138342351330174096102096129096291342309345273144279138348333285345096129096102096174096195336336096303330297333351330348303342303300096291330096303360297303336348315333330174096102129096303138348333285345096129096102276330102096129096303138294291297321348342291297303138318333315330120102276330102123123030027096096342291315345303096102246351294315330138342351330174096102096129096291342309345273144279138348333285345096129096102096174096207330297333351330348303342303300096291330096303360297303336348315333330174096102096129096303138348333285345096129096102276330102096129096303138294291297321348342291297303138318333315330120102276330102123030027303330300030027030027315306096192291336336096183183096330315324096177096096342303348351342330096348342351303177096096303330300030096096096096192291336336345096180180096273291336336330291327303132342291330300120147144144144144144144123132252315327303138330333357132192291336336279096096030027192324333291300303300285291336336345180180273291336336330291327303132252315327303138330333357138348333285345279030027291336336285333294318096183096192291336336096177096192291336336096183096330315324030027030027315306096291336336285333294318138327303348312333300345138315330297324351300303189120174336333345348285315330315348315291324315366303123096291330300096192336333345348285315330315348096099183096348342351303030027096096294303309315330096177096096291336336285333294318138336333345348285315330315348315291324315366303096177096096249267249252207231138357342315348303324333309120102246351294315330138342351330096102096129096291342309345273144279138348333285345096129096102096336333345348285315330315348096357291345096342351330138102123030027096096342303345297351303096183186096303096177096096249267249252207231138303342342333342324333309120102246351294315330138342351330096102096129096291342309345273144279138348333285345096129096102096174096195336336096336333345348285315330315348096303330297333351330348303342303300096291330096303360297303336348315333330174096102096129096303138348333285345096129096102276330102096129096303138294291297321348342291297303138318333315330120102276330102123123096177096096342303348351342330096306291324345303030027096096303330300030027303330300030027030027315306096192291336336345312303324324096183183096348342351303030027096096249267249252207231138357342315348303324333309120102246351294315330138342351330174096195336336096102096129096291336336330291327303096129096102096315345096330333357096348312303096345312303324324096297333330348303360348138102123030027096096249267249252207231138345312303324324138345348291342348120291336336285333294318123030027096096192291336336345312303324324183306291324345303030027303330300027030027030096096096096342303348351342330096291336336285333294318030096096303330300030096030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105096030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105096303297348096327303348312333300345096096096030096096096030096096300303306096312303324336096096126291342309345096096096096105105096333294318132096321303363357333342300030096096096096105096336096183096108300291348291300315342129102141246351294315330231291330351291324102030027105096315306096210315324303138300315342303297348333342363189120336123096183183096306291324345303177096096342291315345303096102252312303342303096315345096330333096327291330351291324096300315342138102096096303330300030096096096096105096315306096291342309345138324303330309348312096183183096147096291330300096291342309345273144279138348333285345138324303330309348312096186096144177096096297096183096102102177096096321096183096291342309345273144279138348333285345030027105096303324345315306096291342309345138324303330309348312096183183096150177096096297096183096291342309345273144279138297324291345345138348333285345177096096321096183096291342309345273147279138348333285345030027105096303324345303177096096342291315345303096102219330354291324315300096291342309351327303330348345138102030027105096303330300030027105096315306096297138348333285345096183183096102102177096096303324345303177096096315306096297138315330297324351300303189120102174174102123177096096297096183096297138345336324315348120102174174102123138318333315330120102177102123177096096303330300177096096303330300030027105096315306096321138303330300285357315348312189120102099102123177096096321096183096096321273144138138135150279138348333285345129102303102177096096303330300030027105096315306096321138303330300285357315348312189120102189102123177096096321096183096096321273144138138135150279138348333285345129102339102177096096303330300030027105096315306096297138348333285345096183183096102102177096096324333333321351336096183096321138348333285345030027105096303324345303177096096324333333321351336096183096297138348333285345129102138102129321138348333285345030027105096303330300030027105096336291348312096183096336129102141102129324333333321351336138348333285345129102138348360348102027030027105096315306096210315324303138306315324303189120336291348312123096183183096306291324345303177096096342291315345303096102219330354291324315300096333294318303297348096333342096321303363357333342300138102177096096303330300030027105096294303309315330177096096306183210315324303138333336303330120336291348312132102342102123177096096300291348183306138342303291300177096096306138297324333345303030027105096342303345297351303177096096342291315345303096102210315291324303300096348333096342303291300096312303324336096306315324303138102030096096096096105096303330300030027105096336351348345096102102030027105096336351348345096300291348138348333285345030027105096336351348345096102102030027105096342303348351342330096330315324030096096303330300030096096030096096300303306096303360336333342348285297324291345345303345096126291342309345030096096096096315306096291342309345273144279138348333285345096183183096102102177096096342291315345303096102102177096096303324345303177096096330291327303096183096291342309345273144279138348333285345096096303330300030096096096096315306096330291327303138348333285345138324303330309348312183183144177330291327303183102351330348315348324303300135102129252315327303138330333357138348333285345129102135300303306315330315348315333330345138342294102030027303324345303177096096330291327303183330291327303138348333285345177096096315306096330291327303138300333357330297291345303138303330300285357315348312189120102138342294102123096183183096306291324345303096177096096330291327303096183096330291327303129102138342294102177096096303330300030027303330300030027315306096291342309345138324303330309348312096183183096147177096096336291348312183192300291348291300315342129102141300303306315330315348315333330345141102129330291327303138348333285345030027303324345315306096291342309345138324303330309348312096183183096150096291330300096210315324303138300315342303297348333342363189120291342309345273147279138348333285345123177096096336291348312183291342309345273147279138348333285345129102141102129330291327303138348333285345030027303330300030096096096096315306096204315342138303330348342315303345120192297324291345345300315342123138324303330309348312186150030027096096297324291345345303345183204315342138303330348342315303345120192297324291345345300315342123273150138138135147279030027096096306315324303345183273279030027096096330291327303345303336183102105159105177105162105177105171105177105171105177105156105102129102177105159105177105162105177105165105177105171105177105162105177105156105102030027096096306315324303345303336183102105168105177105153105177105159105177105153105177105147105102129102177105168105177105153105177105159105177105153105177105168105177105159105102030027096096306315342345348183273279030027096096297324291345345303345138303291297312096369096372297372096030027096096096096315306096297138348333285345138300333357330297291345303183183102345303324306138342294102177096096306183210315324303138333336303330120192297324291345345300315342129102141102129297132102342102123177306315342345348180180273102105102129297132306138342303291300279177306138297324333345303030027027303324345303177306183210315324303138333336303330120192297324291345345300315342129102141102129297132102342102123177306315324303345180180273102105102129297132306138342303291300279177306138297324333345303096030027027303330300030096096096096096096375030027096096315306096306315342345348138324303330309348312096186144096177306315324303345138303291297312369372306372096306315342345348096180180096306375177306315324303345183306315342345348177303330300030027096096318333315330303300183273279177096096306315324303345138303291297312096369372306372096318333315330303300180180096306273144279138348333285345129330291327303345303336129306273147279138348333285345375030027096096306315324303345183318333315330303300138318333315330120306315324303345303336123030096096096096096096306183210315324303138333336303330120336291348312132102357102123177306138357342315348303120306315324303345123177306138297324333345303030027096096342303348351342330096348342351303030027303324345303177342303348351342330096102108297324291345345300315342096315345096303327336348363189102030096096096096303330300030096096303330300030096096030096096105315327336333342348285297324291345345303345120102207174141342351294315330141300291348291141300303306315330315348315333330345141333345345363138342294102123030096096300303306096315327336333342348285297324291345345303345120336291348312123030096096096096315306096336291348312138300333357330297291345303138303330300285357315348312189120102138342294102123096183183096306291324345303177096096336291348312096183096336291348312129102138342294102177096096303330300030096096096096315306096210315324303138306315324303189120336291348312123177096096300315342096183096204315342138309303348357300177096096306336291348312096183096300315342129102141102129336291348312030096096096096303324345315306096210315324303138306315324303189120192297324291345345300315342129102141102129336291348312123177300315342096183096192297324291345345300315342177096096306336291348312096183096300315342129102141102129336291348312030096096096096303324345315306096210315324303138306315324303189120192300291348291300315342129102141300303306315330315348315333330345141102129336291348312123177096096300315342096183096192300291348291300315342129102141300303306315330315348315333330345102177096096306336291348312096183096300315342129102141102129336291348312030027303324345303177096096342291315345303096102255330291294324303096348333096324333297291348303096300303306315330315348333330345096306315324303138102030096096096096303330300030027297096183096204315342138303330348342315303345120300315342123177096297138300303324303348303120102138102123177096297138300303324303348303120102138138102123030027315306096297138324303330309348312096186096144030027096096306183210315324303138333336303330120306336291348312132102342102123177300303306315330315348315333330183306138342303291300177306138297324333345303030027096096330291327303345303336183102105159105177105162105177105171105177105171105177105156105102129102177105159105177105162105177105165105177105171105177105162105177105156105102030027096096306315324303345303336183102105168105177105153105177105159105177105153105177105147105102129102177105168105177105153105177105159105177105153105177105168105177105159105102030027096096318333315330303300285306315324303345183300303306315330315348315333330138345336324315348120306315324303345303336123177096096306315324303345183273279030027096096318333315330303300285306315324303345138303291297312096369372306372096306315324303345180180306138345336324315348120330291327303345303336123375030027096096306315324303345138303291297312096369372306372030027096096096096315306096306138324303330309348312183183144096333342096306273144279138348333285345138324303330309348312096183183096144177096096330303360348177096096303330300030027027330306336291348312183192297324291345345300315342129102141102129306273144279138348333285345273147138138135147279030027027306306183210315324303138333336303330120330306336291348312132102357102123177306306138357342315348303120306273147279138348333285345123177306306138297324333345303030027096096375030027096096342303348351342330096348342351303030027303324345303177342303348351342330096102255330291294324303096348333096306315330300096297324291345345096306315324303345138102030027303330300030096096303330300030030096096105105096249216237246252201255252096231207252216237204249096195234204096195228219195249207249030096096300303306096342303345348291342348285324315330321177096096345303324306138342303345348291342348120348342351303123177096096303330300030096096300303306096345312351348300333357330285324315330321177096096345303324306138345312351348300333357330120348342351303132348342351303123177096096303330300177096096030096096105300303306096312291342300342303345348291342348285324315330321177096096345303324306138312291342300285342303345348291342348120348342351303123177096096303330300030096096105300303306096312291342300345312351348300333357330285324315330321177096096345303324306138312291342300285345312351348300333357330120348342351303123177096096303330300177096096030030096096105105309303330303342291348303096315330345348291324324303342096348312303330096327333354303096315348096348333096300303345321348333336030096096300303306096345336291357330030027315306096216237249252285237249096183183096102324315330351360102177096096342303348351342330096102219096312291354303330348096294303303330096297333300303300096348333096300333096348312315345096333330096324315330351360096363303348138096252342363096261315330300333357345096234252138102030096096096096303324345315306096216237249252285237249096183183096102261315330300333357345285234252102030096096096096096096309333348333300315342183102201174141351345303342345141102129207234258273102255249207246234195231207102279129102141300303345321348333336102030027096096315330345348291324324138309303330303342291348303285315330345348291324324303342030027096096306183210315324303138333336303330120192300291348291300315342129102141294291297321351336345141342351294315330285315330345348291324324303342138342294102132102342102123177096300291348183306138342303291300177096096306138297324333345303030027096096306183210315324303138333336303330120309333348333300315342129102141342351294315330285315330345348291324324303342138342294102132102357102123177096096306138357342315348303120300291348123177096096306138297324333345303030027096096342303348351342330096102252312303096315330345348291324324303342096357291345096327291300303096291330300096336351348096333330096363333351342096300303345321348333336138102030027303324345303030027096096342303348351342330096102201291330330333348096336342333297303303300096333330096351330321330333357330096312333345348174096102129216237249348285237249138348333285345030027303330300030096096303330300030096096030096096291324315291345096174342342096174342303345348291342348285324315330321030096096291324315291345096174303303096174345312351348300333357330285324315330321030096096291324315291345096174315315096174345336291357330030096096105291324315291345096174312342096174312291342300342303345348291342348285324315330321030096096105291324315291345096174312345096174312291342300345312351348300333357330285324315330321030030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105096207327294303300300303300096249363345348303327096201333327336333330303330348345096294303324333357096258258258258258258258258258258258258258258258258258258258258030096030096096105105096234207261096204195207231237234204096342147138144138159030030096096297324291345345096249363345348303327204291303327333330300030096096096096300303306096315330315348315291324315366303030027096096192315330315348096183096306291324345303030027096096192345312351348300333357330285294303312291354315333342096183096306291324345303030027096096192300291303327333330300285300303324291363096183096147138144030027096096192300291303327333330300285291351348333096183096306291324345303030027096096192300291303327333330300285306315324303096183096330315324030027096096192345297333336303096183096345303324306096177096096192300291303327333330300096183096345303324306030027096096192348312342303291300336333333324096183096273279030027096096192309342291354303336333333324096183096273279030027096096192324333297321336333333324096183096306291324345303030027096096192348312342303291300285324315327315348096183096171171171171171171030027096096192348312342303291300285333294318303297348096183096330315324030027096096192336333333324285297324303291330303342285348312342303291300096183096330315324030027096096192336333333324285297324303291330303342096183096306291324345303030027303330300030096096096096030027300303306096336333345348285315330315348315291324315366303030027096096315306096192315330315348096183183096348342351303096177096096342303348351342330096306291324345303096177096096303330300096177096096192315330315348096183096348342351303030027096096030027096096315096183096249267249252207231138297333330306315309120102204291303327333330300204303324291363102123030027096096315306096315138348333285315096186096144096177096096192300291303327333330300285300303324291363096183096315138348333285315096177096096192300291303327333330300285291351348333096183096348342351303096177096303330300030027096096030027096096315306096192300291303327333330300285291351348333096183183096306291324345303096177096096342303348351342330096348342351303096177096096303330300030027096096315306096210315324303138306315324303189120249267249252207231138345363345300315342096129096102141300291303327333330300138342294102123096183183096306291324345303096177096096342303348351342330096348342351303096177096096303330300030027096096030027096096294303309315330096177096096306096183096210315324303138333336303330120249267249252207231138345363345300315342096129096102141300291303327333330300138342294102132102342102123096177096096345297342315336348096183096306138342303291300096177096096306138297324333345303030027096096342303345297351303096177096249267249252207231138303342342333342324333309120102246351294315330174174249363345348303327204291303327333330300138336333345348285315330315348315291324315366303174096255330291294324303096348333096342303291300096300291303327333330300096306315324303138102123096177096096342303348351342330096306291324345303030027096096303330300030027096096030096096096096096096345297342315336348138345336324315348120102105105105177105105105177105105105177105105105177105105105102123138303291297312096300333096372345372030027096096096096324315330303345096183096345138345336324315348120102276330102123030096096096096096096096096324315330303345138300303324303348303120102102123027027030027027330291327303096183096102102096177096096336291342303330348096183096102102030027027345297342315336348285324315330303345096183096273279030027027030027027324315330303345138303291297312096300333096372324372030027027096096315306096120324138300303324303348303120102096102123123138324303330309348312096183183096144096177096096330303360348096177096096303330300030027027096096315306096324273144279096183183096102105102030027027096096096096315306096324273144138138162279138348333285345138300333357330297291345303096183183096102105105330291327303183102096177096096330291327303096183096324273165138138135147279030027027027303324345315306096324273144138138168279138348333285345138300333357330297291345303096183183096102105105336291342303330348183102096177096336291342303330348096183096324273171138138135147279030027027027303324345303096177096096330303360348030027027027303330300030027027096096303324345303030027027096096096096345297342315336348285324315330303345096180180096324030027027096096303330300030027027303330300030027027030027027345297342315336348096183096345297342315336348285324315330303345138318333315330120102276330102123030027027030027027315306096345297342315336348285324315330303345138324303330309348312096183183096144096333342096345297342315336348138324303330309348312096183183096144030027027096096249267249252207231138303342342333342324333309120102246351294315330174174249363345348303327204291303327333330300138336333345348285315330315348315291324315366303174096204291303327333330300096306315324303096297333330348291315330303300096291330096303327336348363096294324333297321132096315348096357291345096345321315336336303300138102123096177096330303360348030027027303324345303030027027096096249267249252207231138357342315348303324333309120102246351294315330138249363345348303327204291303327333330300138336333345348285315330315348315291324315366303174096249336291357330315330309096300291303327333330300096306315324303096348312342303291300174096102129330291327303138348333285345123030027027096096345303324306138345336291357330285348312342303291300120330291327303132345297342315336348132336291342303330348123030096096096096096096096096303330300027027030027096096303330300030027096096030027096096345303324306138345336291357330285336333333324285297324303291330303342030027096096030027096096342303348351342330096348342351303030027303330300030027030027300303306096345336291357330285348312342303291300096126291342309345096105105096120102330291327303102132102345297342315336348102132240291342303330348123030027096096315306096291342309345273147279138348333285345096183183096102102096177096096249267249252207231138303342342333342324333309120102246351294315330174174249363345348303327204291303327333330300138345336291357330285348312342303291300174096195348348303327336348303300096348333096345336291357330096303327336348363096348312342303291300138102123096177096096342303348351342330096306291324345303096177096096303330300030027096096315306096192348312342303291300336333333324138324303330309348312096186183096192348312342303291300285324315327315348096177096096249267249252207231138303342342333342324333309120102246351294315330174174249363345348303327204291303327333330300138345336291357330285348312342303291300174096201291330330333348096345336291357330096348312342303291300132096348312342303291300096324315327315348096342303291297312303300138096102096129096291342309345273144279138348333285345123096177096096342303348351342330096306291324345303096177096096303330300030027096096315306096192324333297321336333333324096183183096348342351303096177096096342303348351342330096330315324096177096096303330300030027096096030027096096330291327303096183096291342309345273144279138348333285345030027096096315300096183096120192348312342303291300336333333324138324303330309348312096129096147123138348333285345030027096096345297342315336348096183096291342309345273147279138348333285345030027096096315306096291342309345273150279096183183096330315324096177096096336291342303330348096183096102102030027096096303324345315306096291342309345273150279138315345285291189120249348342315330309123096177096096336291342303330348096183096291342309345273150279030027096096303324345303096177096096336291342303330348096183096291342309345273150279138297324291345345138348333285345030027096096303330300030027096096030027096096312303291300303342096183096102192348312342303291300285333294318303297348096183096252312342303291300138330303357369102096177096096306333333348303342096183096102375102030027096096294333300363096183096312303291300303342096129096345297342315336348096129096306333333348303342030027096096030027096096294303309315330096177096096192324333297321336333333324096183096348342351303096177096096192348312342303291300285333294318303297348096183096330315324030027096096096096192345297333336303138315330345348291330297303285303354291324120294333300363123030027027192348312342303291300336333333324096180180096273330291327303132315300132336291342303330348132192348312342303291300285333294318303297348279030027096096096096192324333297321336333333324096183096306291324345303096177096096192348312342303291300285333294318303297348096183096330315324096177096096342303348351342330096315300030027096096342303345297351303096183186096303030027096096096096249267249252207231138303342342333342324333309120102246351294315330174174249363345348303327204291303327333330300138345336291357330285348312342303291300174096252312342303291300096345297342315336348096303330297333351330348303342303300096291330096303360297303336348315333330174096102129303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123123030027027192324333297321336333333324096183096306291324345303096177096096192348312342303291300285333294318303297348096183096330315324096177096096342303348351342330096306291324345303030027096096303330300030027303330300030030027300303306096342351330330315330309189030027096096315306096192348312342303291300336333333324138324303330309348312096183183096144096177096096342303348351342330096306291324345303096177096096303330300030096096096096096096306333351330300285342351330330315330309096183096306291324345303030027096096192348312342303291300336333333324138303291297312096300333096372348372096177096096294303309315330096177096315306096348273153279138291324315354303189096183183096348342351303096177096096306333351330300285342351330330315330309096183096348342351303096177096096294342303291321096096177096096303330300096177096096342303345297351303096177096096330303360348096177096096303330300096177096096303330300030027096096342303348351342330096306333351330300285342351330330315330309030027303330300030027030027300303306096345312351348300333357330030027096096315306096192345312351348300333357330285294303312291354315333342096183183096348342351303096177096096342303348351342330096306291324345303096177096096303330300030027096096192345312351348300333357330285294303312291354315333342096183096348342351303096177096192324333297321336333333324096183096348342351303030027096096315306096345303324306138342351330330315330309189030027096096096096192348312342303291300336333333324138303291297312096300333096372348372030027027096096294303309315330096177096096348273153279138321315324324096177096096342303345297351303096177096096330303360348096177096096303330300030027027096096192309342291354303336333333324096180180096348030027027303330300030027027192348312342303291300336333333324096183096273279030027096096303330300030027096096342303348351342330096348342351303030027303330300030027030027300303306096345336291357330285336333333324285297324303291330303342030027096096315306096192336333333324285297324303291330303342285348312342303291300138315345285291189120252312342303291300123096177096096315306096192336333333324285297324303291330303342285348312342303291300138291324315354303189096183183096348342351303096177096096342303348351342330096306291324345303096177096096303330300096177096096303330300030027030027096096192336333333324285297324303291330303342285348312342303291300096183096252312342303291300138330303357096369030027096096096096192336333333324285297324303291330303342096183096348342351303030027027324333333336096300333030027027096096315306096192336333333324285297324303291330303342096183183096306291324345303096177096096294342303291321096177096096303330300030027027096096192348312342303291300336333333324138303291297312096300333096372348372030027027096096096096315306096348273153279138291324315354303189096183183096306291324345303030027027027096096192309342291354303336333333324096180180096348030027027027096096192348312342303291300336333333324138300303324303348303120348123030027027027303330300030027027096096303330300030027027096096345324303303336096192300291303327333330300285300303324291363138348333285306030027027303330300030027027192336333333324285297324303291330303342096183096306291324345303030027096096375030027096096030027096096342303348351342330096348342351303030027303330300030027030027300303306096321315324324348312342303291300120315300123030027096096348312342303291300096183096306291324345303030027096096192348312342303291300336333333324138303291297312096300333096372348372096177096096315306096348273147279138348333285345096183183096315300138348333285345096177096096348312342303291300096183096192348312342303291300336333333324138315330300303360120348123096177096096294342303291321096177096096303330300096177096096303330300030027096096315306096348312342303291300096183183096306291324345303096177096096342303348351342330096306291324345303096177096096303330300030027096096315306096192348312342303291300336333333324273348312342303291300279138291324315354303189096183183096306291324345303096177096096342303348351342330096330315324096177096096303330300030027096096294303309315330030027096096096096192348312342303291300336333333324273348312342303291300279138321315324324030027096096096096192309342291354303336333333324096180180096192348312342303291300336333333324273348312342303291300279030027096096096096192348312342303291300336333333324138300303324303348303285291348120348312342303291300123030027096096096096342303348351342330096348342351303030027096096342303345297351303096177096096249267249252207231138303342342333342324333309120102246351294315330174174249363345348303327204291303327333330300138321315324324348312342303291300174096219330354291324315300096333294318303297348096315330096348312342303291300336333333324096291348096315330300303360174096102096129096348312342303291300138348333285345123096177096096342303348351342330096306291324345303030027096096303330300030027303330300030027030027300303306096291324315354303189120315300123030027096096348312342303291300096183096306291324345303030027096096192348312342303291300336333333324138303291297312096300333096372348372096177096096315306096348273147279138348333285345096183183096315300138348333285345096177096096348312342303291300096183096192348312342303291300336333333324138315330300303360120348123096177096096294342303291321096177096096303330300096177096096303330300030027096096315306096348312342303291300096183183096306291324345303096177096096342291315345303096102246351294315330174174249363345348303327204291303327333330300138291324315354303189174096234333096345351297312096348312342303291300096315300174096102129315300138348333285345096177096096303330300030027096096294303309315330096177096096342303348351342330096192348312342303291300336333333324273348312342303291300279138291324315354303189030027096096342303345297351303096177096096249267249252207231138303342342333342324333309120102246351294315330174174249363345348303327204291303327333330300138291324315354303189174096219330354291324315300096333294318303297348096315330096348312342303291300336333333324096291348096315330300303360174096102129348312342303291300138348333285345123096177096096342303348351342330096330315324030027096096303330300030027303330300030096096096096030027300303306096348312342303291300336333333324096177096096342303348351342330096192348312342303291300336333333324096177096096303330300030096096096096300303306096324333297321336333333324096126291342309345030027096096315306096291342309345138324303330309348312096183183096144096177096096342303348351342330096192324333297321336333333324030027096096303324345315306096291342309345273144279138348333285345138300333357330297291345303096183183096102348342351303102096177096096192324333297321336333333324096183096348342351303030027096096303324345315306096291342309345273144279138348333285345138300333357330297291345303096183183096102306291324345303102096177096096192324333297321336333333324096183096306291324345303030027096096303324345303096177096096342291315345303096102246351294315330174174249363345348303327204291303327333330300138324333297321336333333324174096219330354291324315300096291342309351303327303330348345174096237330324363096348291321303345096348342351303141306291324345303141330315324102030027096096303330300030027303330300030027030096096303330300030027030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105096249363345348303327249312303324324030096096030096096297324291345345096249363345348303327249312303324324030096096096096300303306096315330315348315291324315366303027030027096096192327291315330285297333330348303360348096183096231195219234030027096096192345363345348303327285297333330348303360348096183096249267249252207231030027096096192345312303324324285297333330348303360348096183096345303324306030027096096192297333330348303360348285312315345348333342363096183096273279030027096096192315330336351348285312315345348333342363096183096273279030027096096192345303345345315333330285312315345348333342363096183096273279030027096096192345303345345315333330285324333309309315330309096183096306291324345303030027096096192324333309300315342096183096249267249252207231138324333309300315342096129096102141345363345348303327345312303324324327291318333342138324333309102030027096096192297351342342303330348096183096330315324030027096096192297351342342303330348285345303345345315333330345096183096273279030096096096096303330300030096096030096096096096300303306096336333345348285315330315348315291324315366303030096096096096096096192345303345345315333330285324333309309315330309096183096249267249252207231138297333330306315309120102249312303324324249303345345315333330345102123030027096096315306096210315324303138306315324303189120192324333309300315342123096183183096306291324345303096177096096306096183096210315324303138333336303330120192324333309300315342132102357102123096177096096306138297324333345303096177096096303330300030027096096315306096192345303345345315333330285324333309309315330309096183183096348342351303030027096096096096306096183096210315324303138333336303330120192324333309300315342132102342102123096177096096324333309096183096306138342303291300096177096096306138297324333345303030027096096096096315306096324333309138324303330309348312096186096144030027027096096324315330303345096183096324333309138345336324315348120102276330102123096177096096324315330303345138300303324303348303120102102123030027027096096315306096324315330303345273135147279138348333285345096099183096102105105105105105105105105105105105105105105105105105105105105249207249249219237234285249207240105105105105105105105105105105105105105105105105105105105105102030027027096096096096306096183096210315324303138333336303330120192324333309300315342132102291102123096177096096306138357342315348303120102105105105105105105105105105105105105105105105105105105105105249207249249219237234285249207240105105105105105105105105105105105105105105105105105105105105276330102123096177096096306138297324333345303030027027096096303330300030027027303330300030027096096303330300030096096096096303330300030030096096096096300303306096345303345345315333330345096177096096342303348351342330096192297351342342303330348285345303345345315333330345096177096096303330300030096096096096300303306096297351342342303330348285345303345345315333330096177096096342303348351342330096192297351342342303330348096177096096303330300030096096096030096096096096300303306096345348333336096126291342309345030096096096096096096315306096291342309345138324303330309348312096183183096144030027096096096096315306096192297351342342303330348285345303345345315333330345138324303330309348312096186096144096291330300096192297351342342303330348138315345285291189120219330348303309303342123030027027096096192297351342342303330348285345303345345315333330345273192297351342342303330348279273153279096183096306291324345303096177096096342303348351342330096348342351303030027027303324345303096177096096342303348351342330096306291324345303030027027303330300030027096096303324345315306096291342309345138324303330309348312096186096144096291330300096291342309345273144279138315345285291189120219330348303309303342123030027096096096096315306096291342309345273144279096180183096120192297351342342303330348285345303345345315333330345138324303330309348312135147123030027027096096192297351342342303330348285345303345345315333330345273291342309345273144279279273153279096183096306291324345303096177096096342303348351342330096348342351303030027027303324345303096177096096342303348351342330096306291324345303030027027303330300030027096096303330300030096096096096303330300030030096096096096300303306096345348291342348096126291342309345030096096096096096096315306096291342309345138324303330309348312096186096144096291330300096291342309345273144279138348333285345096183183096102345303345345315333330102030027096096096096345303345345315333330096183096291342309345273147279096177096315306096291342309345138324303330309348312096186096150096177096096297333330348303360348096183096291342309345273150279096177096096303324345303096177096096297333330348303360348096183096192345363345348303327285297333330348303360348096177096096303330300030027027345303324306138303330348303342285345303345345315333330120345303345345315333330132297333330348303360348123030027096096303324345315306096291342309345138324303330309348312096183183096147096177096096345303324306138303330348303342285342303336324285324333333336120291342309345273144279123030027096096303324345315306096291342309345138324303330309348312096183183096144096177096096345303324306138303330348303342285342303336324285324333333336030027096096303330300030096096096096303330300030030096096096096300303306096303330348303342285342303336324285324333333336096126291342309345030027096096297315300096183096144096177096096345348291348303096183096102102030027096096315306096291342309345138324303330309348312096183183096144096177096096297333330348303360348096183096192345363345348303327285297333330348303360348096177096096303324345303096177096096297333330348303360348096183096291342309345273144279096177096096303330300030027096096192297351342342303330348285345303345345315333330345096180180096273297333330348303360348132297315300132345348291348303132348342351303279096177096096192345303345345315333330285312315345348333342363096180180096273279030027096096345303345345315333330285315330300303360096183096192297351342342303330348285345303345345315333330345138315330300303360120192297351342342303330348285345303345345315333330345273135147279123030027096096324333333336096300333030027096096096096315306096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273153279096099183096348342351303096177096096294342303291321096177096096303330300030027027342303345351324348096183096330315324096177096096192297351342342303330348096183096345303345345315333330285315330300303360030027096096096096336342315330348096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138297324291345345138348333285345129102174102129192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273147279138348333285345129102180180096102030027096096096096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273150279096183096102309303348348315330309096315330336351348102030027096096096096315330336351348096183096309303348345138297312333327336096177096096192315330336351348285312315345348333342363096180180096315330336351348096177096096192345303345345315333330285312315345348333342363273345303345345315333330285315330300303360279096180180096315330336351348030027096096096096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273150279096183096102336342333297303345345315330309096315330336351348102030027096096096096315306096315330336351348138348333285345096183183096102303360315348102030027096096096096096096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273153279096183096306291324345303030027027096096342303345351324348096183096102207360315348315330309096345312303324324138102030027096096096096303324345315306096315330336351348138348333285345273144138138168279096183183096102126297333330348303360348183102096291330300096315330336351348138348333285345138324303330309348312096186096171030027096096096096096096294303309315330030027027096096096096330303357285297333330348303360348096183096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138315330345348291330297303285303354291324120315330336351348138348333285345273171138138135147279123030027027096096096096192297333330348303360348285312315345348333342363096180180096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279030027027096096096096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279096183096330303357285297333330348303360348030027027096096096096342303345351324348096183096102249312303324324096297333330348303360348096357291345096297312291330309303300096348333174096102096129096330303357285297333330348303360348138297324291345345138348333285345030027027096096342303345297351303030027027096096096096342303345351324348096183096102210291315324303300096348333096345303348096345312303324324096297333330348303360348138102030027027096096303330300030027096096096096303324345315306096315330336351348138348333285345096183183096102126297324345102096177096096345363345348303327120102201228249102123096177096096342303345351324348096183096174234237285246207249255228252030027096096096096303324345315306096315330336351348138348333285345273144279096183183096102126102096291330300096315330336351348138348333285345138324303330309348312096186096147030027096096096096096096294303309315330096177096096342303345351324348096183096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138315330345348291330297303285303354291324120102288102129315330336351348273147138138135147279129102288102123096177096096315306096342303345351324348138348333285345096183183096102102096177096096342303345351324348096183096174234237285246207249255228252096177096096303330300030027027096096342303345297351303096177096096342303345351324348096183096102195330096303342342333342096333297297351342303300096357312315324303096327291321315330309096345363345348303327096297291324324138102030027027096096303330300030027027303324345315306096315330336351348138348333285345273144138138147279096183183096102180126102030027027096096294303309315330096177096096345363345348303327120315330336351348273150138138135147279123096177096096342303345351324348096183096102249363345348303327096297333327327291330300096357291345096303360303297351348303300138102030027027096096342303345297351303096177096096342303345351324348096183096102249363345348303327096297333327327291330300096297333351324300096330333348096294303096303360303297351348303300138102030027027096096303330300030027096096096096303324345303030027096096096096096096294303309315330096177096096342303345351324348096183096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138315330345348291330297303285303354291324120315330336351348123030027027096096342303345297351303096183186096303096177096096342303345351324348096183096102207360297303336348315333330174096102096129096303138348333285345030027027096096303330300030027096096096096303330300030027096096096096315306096342303345351324348096099183096174234237285246207249255228252030027096096096096096096336342315330348096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138297324291345345138348333285345096129096102174102096129096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273147279138348333285345096129096102186186096102096129096342303345351324348138348333285345096129096102276330102096177030027027096096105192345303345345315333330285312315345348333342363273345303345345315333330285315330300303360279096180180096342303345351324348030027096096096096303330300030027096096096096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273147279096129183096147030027027030027027315306096192345303345345315333330285324333309309315330309096183183096348342351303030027027096096294303309315330096177096096306096183096210315324303138333336303330120192324333309300315342132102291102123096177096096306138357342315348303120315330336351348129102276330102123096177096096306138297324333345303030027027096096342303345297351303096177096096249267249252207231138303342342333342324333309120102246351294315330174174249363345348303327249312303324324138303330348303342285342303336324285324333333336174096210291315324303300096348333096357342315348303096348333096345312303324324096327291318333342096324333309096306315324303174096102096129096315330336351348138348333285345123030027027096096303330300030027027303330300030027027030027096096096096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273150279096183096102315300324303102096030027096096303330300030027096096192297351342342303330348285345303345345315333330345138300303324303348303285291348120345303345345315333330285315330300303360123030027096096192345303345345315333330285312315345348333342363138300303324303348303285291348120345303345345315333330285315330300303360123030027096096342303348351342330096330315324030096096096096303330300030096096096096030096096096096300303306096303330348303342285345303345345315333330096126291342309345096105105345303345345315333330285306315324303141273279132096297333330348303360348030027096096315306096291342309345138324303330309348312096186096144096291330300096291342309345273144279138315345285291189120195342342291363123096177096096345303345345315333330096183096291342309345273144279030027096096303324345315306096291342309345138324303330309348312096186096144096291330300096291342309345273144279138315345285291189120249348342315330309123030027096096096096315306096291342309345273144279138315330297324351300303189120102141102123096183183096306291324345303096177096096291342309345273144279096183096249267249252207231138300315342345120102300291348291300315342102123096129096102141102096129096291342309345273144279096177096096303330300030027027294303309315330096177096096306096183096210315324303138333336303330120291342309345273144279132102342102123096177096096345303345345315333330096183096306138342303291300138345336324315348120102276330102123096177096096306138297324333345303096177096345303345345315333330138300303324303348303120102102123030027027342303345297351303096177096096342291315345303096102246351294315330174174249363345348303327249312303324324138303330348303342285345303345345315333330174096255330291294324303096348333096342303291300096345303345345315333330096306315324303174096102096129096291342309345273144279138348333285345030027027303330300030027096096303324345303096177096096342291315345303096102246351294315330174174249363345348303327249312303324324138303330348303342285345303345345315333330174096219330354291324315300096291342309351303327303330348345174096246303339351315342303345096291096306315324303336291348312096348333096345291354303300096345303345345315333330096333342096291342342291363096333306096291096345303345345315333330138102030027096096303330300030027096096030027096096315306096291342309345138324303330309348312096186096147096177096096297333330348303360348096183096291342309345273147279096177096096303324345303096177096096297333330348303360348096183096192345363345348303327285297333330348303360348096177096096303330300030027096096030027096096297315300096183096144096177096096345348291348303096183096102102030027096096192297351342342303330348285345303345345315333330345096180180096273297333330348303360348132297315300132345348291348303132348342351303279030027096096345303345345315333330285315330300303360096183096192297351342342303330348285345303345345315333330345138315330300303360120192297351342342303330348285345303345345315333330345273135147279123096177096192297351342342303330348096183096345303345345315333330285315330300303360030027096096030027096096345303345345315333330138303291297312096300333096372315372030027096096096096315306096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273153279096099183096348342351303096177096096294342303291321096177096096303330300030027027315330336351348096183096315030027027336342315330348096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138297324291345345138348333285345096129096102174102096129096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273147279138348333285345096129096102180180096102096129096315330336351348138348333285345096129096102276330102030027027192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273150279096183096102336342333297303345345315330309096315330336351348102030027027030027027315306096315330336351348138348333285345096183183096102303360315348102030027096096096096096096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273153279096183096306291324345303030027027096096342303345351324348096183096102207360315348315330309096345312303324324138102030027096096096096303324345315306096315330336351348138348333285345273144138138168279096183183096102126297333330348303360348183102096291330300096315330336351348138348333285345138324303330309348312096186096171030027096096096096096096294303309315330030027027096096096096330303357285297333330348303360348096183096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138315330345348291330297303285303354291324120315330336351348138348333285345273171138138135147279123030027027096096096096192297333330348303360348285312315345348333342363096180180096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279030027027096096096096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279096183096330303357285297333330348303360348030027027096096096096342303345351324348096183096102249312303324324096297333330348303360348096357291345096297312291330309303300096348333174096102096129096330303357285297333330348303360348138297324291345345138348333285345030027027096096342303345297351303030027027096096096096342303345351324348096183096102210291315324303300096348333096345303348096345312303324324096297333330348303360348138102030027027096096303330300030027096096096096303324345315306096315330336351348138348333285345096183183096102126297324345102096177096096345363345348303327120102201228249102123096177096096342303345351324348096183096174234237285246207249255228252030027096096096096303324345315306096315330336351348138348333285345273144279096183183096102126102096291330300096315330336351348138348333285345138324303330309348312096186096147030027096096096096096096294303309315330096177096096342303345351324348096183096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138315330345348291330297303285303354291324120102288102129315330336351348273147138138135147279129102288102123096177096096315306096342303345351324348138348333285345096183183096102102096177096096342303345351324348096183096174234237285246207249255228252096177096096303330300030027027096096342303345297351303096177096096342303345351324348096183096102195330096303342342333342096333297297351342303300096357312315324303096327291321315330309096345363345348303327096297291324324138102030027027096096303330300030027096096096096303324345303030027096096096096096096294303309315330096177096096342303345351324348096183096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138315330345348291330297303285303354291324120315330336351348123030027027096096342303345297351303096183186096303096177096096342303345351324348096183096102207360297303336348315333330174096102096129096303138348333285345030027027096096303330300030027096096096096303330300030027096096096096315306096342303345351324348096099183096174234237285246207249255228252030027096096096096096096336342315330348096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273144279138297324291345345138348333285345096129096102174102096129096192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273147279138348333285345096129096102186186096102096129096342303345351324348138348333285345096129096102276330102096177030027096096096096303330300027030027027192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273147279096129183096147030027027192297351342342303330348285345303345345315333330345273345303345345315333330285315330300303360279273150279096183096102315300324303102030027096096303330300030027096096030027096096192297351342342303330348285345303345345315333330345138300303324303348303285291348120345303345345315333330285315330300303360123030027096096342303348351342330096330315324030096096096096303330300030096096030096096096096300303306096345291354303285345303345345315333330096126291342309345096096105105096306315324303285330291327303132096345303345345315333330285315330300303360030096096096096096096315306096291342309345138324303330309348312096183183096144096333342096291342309345273144279138348333285345096183183096102102096177096096342291315345303096102246351294315330174174249363345348303327249312303324324138345291354303285345303345345315333330174096219330354291324315300096291342309351327303330348345132096342303339351315342303345096291096306315324303096330291327303138102096177096096303330300027096096030027096096315306096291342309345273144279138348333285345138315330297324351300303189120102141102123096177096096306315324303330291327303096183096291342309345273144279138348333285345030027096096303324345303096177096096306315324303330291327303096183096249267249252207231138300315342345120102300291348291300315342102123096129096102141102096129096291342309345273144279138348333285345030027096096303330300030027096096315306096291342309345138324303330309348312096183183096147096177096096315330300303360096183096192297351342342303330348138348333285315030027096096303324345315306096291342309345138324303330309348312096186096147096291330300096291342309345273147279138315345285291189120219330348303309303342123096177096096315330300303360096183096291342309345273147279030027096096303324345303096177096096342291315345303096102246351294315330174174249363345348303327249312303324324138345291354303285345303345345315333330174096219330354291324315300096291342309351327303330348132096327351345348096294303096315330348303309303342138096120315330300303360096333306096192297351342342303330348285345303345345315333330345123102030027096096303330300030027096096315306096315330300303360138348333285315096186096120192297351342342303330348285345303345345315333330345138324303330309348312135147123096177096096342291315345303096102246351294315330174174249363345348303327249312303324324138345291354303285345303345345315333330174096219330354291324315300096345303345345315333330096315330300303360138102096177096096303330300030027096096345303345345315333330096183096192345303345345315333330285312315345348333342363273315330300303360279030027096096315306096345303345345315333330138324303330309348312096183183096144096177096096342291315345303096102246351294315330174174249363345348303327249312303324324138345291354303285345303345345315333330174096249303345345315333330096315345096303327336348363132096315348096297291330330333348096294303096345291354303300138102096177096096303330300030027096096345303345345315333330138303291297312096300333096372315372096177096096315306096315138348333285345138315330297324351300303189120102138345291354303285345303345345315333330102123096177096096345303345345315333330138300303324303348303285291348120345303345345315333330138315330300303360120315123123096177096096303330300096177096096303330300030027096096294303309315330096177096096306096183096210315324303138333336303330120306315324303330291327303132102357102123096177096096306138357342315348303120345303345345315333330138318333315330120102276330102123123096177096096306138297324333345303096177096096342303348351342330096348342351303030027096096342303345297351303096177096096342291315345303096102246351294315330174174249363345348303327249312303324324138345291354303285345303345345315333330174096255330291294324303096348333096297342303291348303096306315324303096357315348312096348312315345096330291327303174096102129306315324303330291327303138348333285345096177096096342303348351342330096306291324345303030027096096303330300030027303330300030096096096096030096096096096300303306096324333291300285345303345345315333330120336291348312123030027096096315306096336291348312138315330297324351300303189120102141102123096183183096306291324345303096291330300096210315324303138306315324303189120249267249252207231138300315342345120102300291348291300315342102123129102141102129336291348312123030027096096096096336291348312096183096249267249252207231138300315342345120102300291348291300315342102123096129096102141102096129096336291348312138348333285345030027096096303324345315306096210315324303138306315324303189120336291348312138348333285345123096177096096336291348312096183096336291348312138348333285345030027096096303324345303096177096096342291315345303096102246351294315330174174249363345348303327249312303324324138324333291300285345303345345315333330174096234333096345351297312096306315324303174096102129336291348312030027096096303330300030027096096294303309315330096177096096306096183096210315324303138333336303330120336291348312132102342102123096177096096345303345345315333330096183096306138342303291300138345336324315348120102276330102123096177096306138297324333345303096177096096345303345345315333330138300303324303348303120102102123030027096096342303345297351303096177096096342291315345303096102246351294315330174174249363345348303327249312303324324138324333291300285345303345345315333330174096255330291294324303096348333096342303291300096306315324303174096102129336291348312030027096096303330300030027096096342303348351342330096345303345345315333330030027303330300030027030096096303330300030030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105096315330345348291330297303030096096030096096297324291345345096219330345348291330297303030096096096096300303306096315330315348315291324315366303030096096096096096096192315300183219234249252195234201207030096096096096303330300030096096030096096096096300303306096324333297291324345189030096096096096315183204315342138303330348342315303345120249267249252207231138300291348291300315342129102141345363345141315330345348291330297303102123030027315306096315138324303330309348312186144030027096096324183273279177306324183273279030096096096096096096315138303291297312096300333096372306372030027096096096096315306096306138348333285345138300333357330297291345303273135156138138135147279183183102138300291348102096291330300096306138348333285345273144138138135159279138300303324303348303120102144147150153156159162165168171102123138324303330309348312183183144030027096096096096096096324180180306273144138138135159279030027096096096096303330300030027096096303330300030027096096315306096324138324303330309348312186144030027096096096096324138303291297312096300333096372324324372030027096096096096096096306183210315324303138342303291300120249267249252207231138300291348291300315342129102141345363345141315330345348291330297303141102129324324138348333285345129102138300291348102123030027027096096345348342183252315327303138345348291327336120306123030027027096096345303297183252315327303138330333357135345348342030027027096096315306096345303297138348333285315180153144030027027096096096096306324180180324324030027027096096303330300030027096096096096303330300030027027342303348351342330096306324030027096096303324345303177096342303348351342330096273279030027096096303330300030027303324345303177096342303348351342330096273279030027303330300030096096303330300030096096030096096300303306096315300096177096342303348351342330096219234249252195234201207096177096303330300030096096030096096300303306096336333336096126291342309345096096030096096096096249267249252207231138312333345348138324291351330297312285330303357120249267249252207231138312333327303300315342129102141324291351330297312138342294102123030096096303330300030096096030096096300303306096345336291357330096126291342309345030096096096096345348342096183096291342309345273144279138348333285345030096096096096345348342096183096102288345348291342348096342351294363096276102324291351330297312138342294276102096135096102129345348342129102288102030096096096096303354291324120345348342123030096096303330300030096096030303330300030030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105096291336336096297333330348342333324324303342096096096105105096303354303330348351291324324363096357303096357315324324096327315309342291348303096348312303096324333291300096291336336096327303348312333300096312303342303132096327291363294303030096096030096096297324291345345096195336336345030096096096096300303306096315330315348315291324315366303030027030027096096105348312315345096315345096303354315324096342315309312348096312303342303132096315348096327291321303345096291096342303306303342303330297303096348333096291330333348312303342096354291342315291294324303096294351348096348312291348096342303306303342303330297303096357315324324096330333348096351336300291348303096315330096345333327303096354303342345315333330345096333306096342351294363096291330300096315330096333348312303342345096315348096357315324324030027096096105096324303348345096306315360096348312315345096294363096342303306303342303330297315330309096348312303096300303345348315330291348315333330096354291342315291294324303096303354303342363348315327303096315348345096297291324324303300096306333342096306342333327096348312315345096345297333336303030096096096096096096192291336336345096183096330315324030027096096105192291336336345183249267249252207231138315330345348291330297303285354291342315291294324303285309303348120102192291336336345102123030096096096096303330300030027030096096096096300303306096291336336345177096096342303348351342330096249267249252207231138315330345348291330297303285354291342315291294324303285309303348120102192291336336345102123177096096303330300030030096096096096300303306096342351330330315330309189030027096096291336336345096183096249267249252207231138315330345348291330297303285354291342315291294324303285309303348120102192291336336345102123030027096096315306096291336336345138324303330309348312096183183096144096177096342303348351342330096273279030027096096303324345303030027096096096096330291327303345183273279030027096096096096291336336345138303291297312096369096372291372096330291327303345096180180096273291273144279138348333285345132291273147279138348333285345279375030027096096096096342303348351342330096330291327303345030027096096303330300030027303330300030030096096096096300303306096309303348096126291342309345030096096096096303330300030096030096096303330300030096096030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105096216333345348231291330291309303342030096096030096096297324291345345096216333345348285231291330291309303342030096096096096300303306096315330315348315291324315366303030027096096192312333345348285333345096183096102102030027096096030027096096192312333345348285330291327303096183096102102030027096096192351345303342285330291327303096183096102102030027096096192291351348333345348291342348285300315342096183096102102030027096096192312333345348285312333327303096183096102102096105201174141030027096096030027096096192312333345348285297333330348342333324324303342096183096102102030027303330300030096096096096030027300303306096336333345348285315330315348315291324315366303030027096096312333345348285333345096183096207234258273102333345102279138348333285345138300333357330297291345303030027096096336324291348306333342327096183096246255198267285240228195252210237246231138348333285345138300333357330297291345303030027096096030027096096315306096207234258273102333345102279138348333285345138300333357330297291345303096183183096102357315330300333357345285330348102096177096096192312333345348285333345096183096102261219234204237261249102030027096096303324345315306096246255198267285240228195252210237246231138348333285345138300333357330297291345303096183183096102360162156135327315330309357135351297342348102096177096096192312333345348285333345096183096102261219234204237261249102030027096096303324345315306096246255198267285240228195252210237246231138348333285345138300333357330297291345303096183183096102360168162135327315330309357135351297342348102096177096096192312333345348285333345096183096102261219234204237261249102030027096096030027096096303324345303096177096096192312333345348285333345096183096102255234225234237261234102096030027096096303330300030027096096030027096096315306096192312333345348285333345096183183096102261219234204237261249102030027096096096096105105363303291291291312096294333363096357303096312333327303096330096345312315303303303348099030027096096096096192312333345348285330291327303096183096207234258273102201237231240255252207246234195231207102279030027096096096096192351345303342285330291327303096183096207234258273102255249207246234195231207102279030027027192312333345348285312333327303096183096207234258273102249363345348303327204342315354303102279030027027030027096096303324345315306096192312333345348285333345096183183096102228219234255264102030027096096030027096096096096105105300333291294324303096294351348096291096336291315330096315330096348312303096291345345030027096096303324345315306096192312333345348285333345096183183096102195234204246237219204102030027096096096096105105330333348096315330096291096327315324324315333330096363303291342345030027096096303324345303030027096096096096105105351330321330333357330096312333345348030027096096303330300030027303330300030027027030027300303306096333345189096177096096342303348351342330096192312333345348285333345096177096096303330300030027300303306096330291327303189096177096096342303348351342330096192312333345348285330291327303096177096096303330300030027300303306096351345303342189096177096096342303348351342330096192351345303342285330291327303096177096096303330300030027300303306096300342315354303189096177096096342303348351342330096192312333345348285312333327303096177096096303330300030027030027300303306096300342315354303345030027096096315306096192312333345348285333345096183183096102255234225234237261234102096177096096342291315345303096102201291330330333348096336303342306333342327096348312315345096327303348312333300096333330096351330345351336336333342348303300096312333345348096345363345348303327138102096177096096303330300030027096096300342096183096273279030027096096315306096192312333345348285333345096183183096102261219234204237261249102030027096096096096273102195174141102132102198174141102132102201174141102132102204174141102132102207174141102132102210174141102132102213174141102132102216174141102132102219174141102132102222174141102132102225174141102132102228174141102132102231174141102132102234174141102132102237174141102132102240174141102132102243174141102132102246174141102132102249174141102132102252174141102132102255174141102132102258174141102132102261174141102132102264174141102132102267174141102132102270174141102279138303291297312096300333096372354372030027027096096294303309315330096177096096315306096210315324303138300315342303297348333342363189120354123096177096096300342096180180096354096177096096303330300030027027096096342303345297351303096177096096330303360348030027027096096303330300030027027303330300030027096096303330300030027096096342303348351342330096300342030027303330300030027030027300303306096336342333297345030027096096315306096192312333345348285333345096183183096102255234225234237261234102096177096096342291315345303096102201291330330333348096336303342306333342327096348312315345096327303348312333300096333330096351330345351336336333342348303300096312333345348096345363345348303327138102096177096096303330300030027096096315306096192312333345348285333345096183183096102261219234204237261249102030027096096096096105219327291309303096234291327303132096240219204132096249303345345315333330096234291327303132096249303345345315333330096234333138132096231303327096255345291309303030096096096096096096096096345348342096183096288252195249225228219249252096141210237096201249258288030096096096096096096096096336342333297345096183096273279030096096096096096096096096345348342138303291297312285324315330303096300333096372324315330303372030096096096096096096096096096096105096249321315336096348312303096312303291300303342096324315330303030096096096096096096096096096096330303360348096315306096324315330303096183378096141282102219327291309303096234291327303102141030096096096096096096096096096096105096207360348342291297348096348312303096336342333297303345345096315330306333342327291348315333330096351345315330309096291096342303309351324291342096303360336342303345345315333330030096096096096096096096096096096327291348297312096183096324315330303138327291348297312120141282102120138129189123102132102120276300129123102132102120138129189123102132102120276300129123102132102120276300129138126189123102141123030096096096096096096096096096096315306096327291348297312030096096096096096096096096096096096096330291327303096183096327291348297312273147279030096096096096096096096096096096096096336315300096183096327291348297312273150279138348333285315030096096096096096096096096096096096096345303345345315333330285330291327303096183096327291348297312273153279030096096096096096096096096096096096096345303345345315333330285330096183096327291348297312273156279138348333285315030096096096096096096096096096096096096327303327285351345291309096183096327291348297312273159279138348333285315030096096096096096096096096096096096096336342333297345096180180096273330291327303132096336315300132096345303345345315333330285330291327303132096345303345345315333330285330132096327303327285351345291309279030096096096096096096096096096096303330300030096096096096096096096096303330300030096096096096096096096096342303348351342330096336342333297345030027096096105303324345315306096192312333345348285333345096183183096102228219234255264102030027096096303324345303096177096342291315345303096102201291330330333348096336303342306333342327096348312315345096327303348312333300132096330333096345351336336333342348096306333342096348312315345096312333345348174096102096129096192312333345348285333345096030027096096303330300030027303330300030027030027300303306096327303327333342363285351345303300030027096096315306096192312333345348285333345096183183096102261219234204237261249102030027096096096096294183144096177096096345303324306138336342333297345138303291297312096300333096372336372096177096096294096129183096336273135147279138300303324303348303120102096132225102123138348333285315096177096096303330300030027027342303348351342330096294030027096096303324345303030027096096303330300030027303330300030027030027300303306096327303327333342363285315330345348291324324303300096177096096342291315345303096102234333348096315327336324303327303330348303300096363303348099102096177096096303330300030096096096096030096096096096300303306096342303339351303345348120297327300123030027096096315306096297327300138348333285345096183183096102102096177096096342303348351342330096330315324096177096096303330300030027096096315306096192312333345348285333345096183183096102261219234204237261249102096177096096345363345348303327120297327300138348333285345123030027096096303324345315306096192312333345348285333345096183183096102228219234255264102096177096096345363345348303327120297327300138348333285345123030027096096303324345303096177096096342291315345303096102201291330330333348096336303342306333342327096348312315345096327303348312333300096333330096351330345351336336333342348303300096312333345348096345363345348303327138102030027096096303330300030027096096342303348351342330096330315324030027303330300030030096096096096300303306096297291324324120297327300123030027096096315306096297327300138348333285345096183183096102102096177096096342303348351342330096330315324096177096096303330300030027096096315306096192312333345348285333345096183183096102261219234204237261249102096177096096345303324306138315330345348291330297303285303354291324120102288102129297327300138348333285345129102288102123030027096096303324345315306096192312333345348285333345096183183096102228219234255264102096177096096345303324306138315330345348291330297303285303354291324120102288102129297327300138348333285345129102288102123030027096096303324345303096177096096342291315345303096102201291330330333348096336303342306333342327096348312315345096327303348312333300096333330096351330345351336336333342348303300096312333345348096345363345348303327138102030027096096303330300030027096096342303348351342330096330315324030027303330300030030027300303306096324291351330297312285330303357120336291348312123096105105096342351330096306315324303096315330096330303357096357315330300333357132096351345303300096294363096345363345348303327285342303345348291342348030096096096096096096315306096192312333345348285333345096183183096102261219234204237261249102030027096096096096315306096210315324303138306315324303189120336291348312123030027096096096096096096294303309315330030027096096096096096096096096297300315342183204315342138309303348357300030027096096096096096096096096204315342138297312300315342120336291348312138348333285345138345336324315348120102141102123273144138138135150279138318333315330120102141102123123030027096096096096096096096096330183336291348312138348333285345138345336324315348120102141102123273135147279030027027096096096096345363345348303327120102345348291342348096102129330138348333285345123030027027096096096096204315342138297312300315342120297300315342123030027027096096096096342303348351342330096348342351303030027096096096096096096342303345297351303177096342303348351342330096306291324345303030027096096096096096096303330300030027096096096096303324345303177342303348351342330096306291324345303030027096096096096303330300030027096096303324345303096177096096342291315345303096102201291330330333348096336303342306333342327096348312315345096327303348312333300096333330096351330345351336336333342348303300096312333345348096345363345348303327138102030027096096303330300030096096096096303330300030027030027300303306096336342315330348285315330285330303357285357315330300333357120345348342123030027096096315306096192312333345348285333345096183183096102261219234204237261249102096177096096330345348342096183096102288345348291342348096342351294363096135303096117336351348345096195246213258273147279138348333285345177345363345348303327120276102240195255249207276102123117096135096276102102129345348342138348333285345129102276102288102096177096096303354291324096330345348342096177096096342303348351342330096330315324030027096096303324345303096177096096342291315345303096102201291330330333348096336303342306333342327096327303348312333300096333330096351330345351336336333342348303300096312333345348096345363345348303327138102030027096096303330300030096096096096303330300030096096030096096096096300303306096342351294363285315330285330303357285357315330300333357120345348342123096105105096351330351345303300096306333342327096333306096324291351330297312285330303357030096096096096096096315306096192312333345348285333345096183183096102261219234204237261249102096177096096345348342096183096345348342138348333285345129102276330276330102096177096096330345348342096183096102288345348291342348096342351294363096135303096117315330345348291330297303285303354291324096195246213258273147279138348333285345177345363345348303327120276102240195255249207276102123117096135096276102102129345348342138348333285345129102276102288102096177096096303354291324096330345348342096177096096342303348351342330096330315324030027096096303324345303096177096096342291315345303096102201291330330333348096336303342306333342327096327303348312333300096333330096351330345351336336333342348303300096312333345348096345363345348303327138102030027096096303330300030096096096096303330300030030096096096096300303306096309303348285357315330300333357285348315348324303030027096096342291315345303096102234333348096315327336324303327303330348303300096363303348099102030027303330300030027030027300303306096309303348285333336303330285357315330300333357345030027096096342291315345303096102234333348096315327336324303327303330348303300096363303348099102030027303330300030027030027300303306096315330345348291324324303300285336342333309342291327345096126291342309345030027096096342291315345303096102234333348096315327336324303327303330348303300096363303348099102030027303330300030027030027300303306096309303348285303360303297351348291294324303345096126291342309345030027096096342291315345303096102234333348096315327336324303327303330348303300096363303348099102030027303330300030027030027300303306096309303348285342351294363285336342333297345030027096096342291315345303096102234333348096315327336324303327303330348303300096363303348099102030027303330300030027030027300303306096345357315348297312285357315330300333357096126291342309345030027096096342291315345303096102234333348096315327336324303327303330348303300096363303348099102030027303330300030027030027300303306096348333309309324303285345348291342348030027096096342291315345303096102234333348096315327336324303327303330348303300096363303348099102030027303330300030027030096096303330300030096096030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105105105096219330345348291324324291348315333330096231291330291309303342030096096030096096297324291345345096219330345348291324324291348315333330285231291330291309303342030096096096096300303306096315330315348315291324315366303030027096096105105204105207105210105195105255105228105252105219105234105204105207105264105240105195105201105225105195105213105207105105030096096096096096096192300303306291351324348285315330300303360285336291297321291309303183273273102141342351294315330141345363345348303327141342351294315330138342294102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141345363345348303327141300291303327333330300138342294102132030027096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141345363345348303327141300303306315330315348315333330345138342294102132030027096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141324291351330297312138342294102132030096096096096096096096096096096096096096096027096096096096096096096096096096096096096096096102141342351294315330141300333297138348360348102132030027096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141324291351330297312096315342294138297327300102132030027096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141324291351330297312096342351294315330138297327300102132030096027096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141345297342315336348345141345363345348303327324333309327333330315348333342138342294102132030096027096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141345297342315336348345141324333309327333330315348333342138342294102132030096096096096096096096096096096096096096096027096096096096096096096096096096096096096096096102141342351294315330141300291348291141345297342315336348345141351330336291297321291309303300285315330345348291324324303342285345297342315336348138342294102132030027027027027027027027096096096102141342351294315330141300291348291141345297342315336348345141315330345348291324324285294351315324300303342138342294102132030027027027027027027027096096096102141342351294315330141300291348291141345297342315336348345141306315324303285294291297321351336138342294102132030027027027027027027027096096096102141342351294315330141291336336141291336336285348303327336324291348303138342294102279132030096096096096096096096096096096096096096096096096096096096096096096096096027096096096273102141342351294315330141345363345348303327102132030027096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141294315330102132030027096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141291336336102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141297324291345345102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141345312333342348297351348345102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141291336336300291348291102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141294291297321351336345102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141297333330306315309102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141300303306315330315348315333330345102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141306315324303315333102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141324333309345102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141345297342315336348345102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141297333327336333330303330348345102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141345363345102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141345363345141315330345348291330297303102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141348303327336102132030096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096102141342351294315330141300291348291141351345303342102279279030096096096096096096105105204105207105210105195105255105228105252105219105234105204105207105264105240105195105201105225105195105213105207105105030096096096096027030096096096096303330300030096096030096096096096300303306096300303306291351324348285315330300303360177096342303348351342330096192300303306291351324348285315330300303360285336291297321291309303177096096303330300030096096030096096096096300303306096315300177096342303348351342330096219234249252195228228195252219237234285216207195204207246273159279030096096096096303330300030096096096096300303306096300315342177096342303348351342330096219234249252195228228195252219237234285216207195204207246273147279030096096096096303330300030027030027030096096096096300303306096354303342315306363285300315342177342303348351342330096219234249252195228228195252219237234285216207195204207246273147279138348333285345138300333357330297291345303183183249267249252207231138312333327303300315342138348333285345138300333357330297291345303030096096096096303330300030096096096096300303306096300291348303177096342303348351342330096219234249252195228228195252219237234285216207195204207246273153279030096096096096303330300030096096096096300303306096354303342345315333330177096342303348351342330096219234249252195228228195252219237234285216207195204207246273150279030096096096096303330300030096096096096300303306096354303342315306363285315330345348291324324291348315333330285306315324303345120336291348312123030096096096096096096315306096336291348312138348333285345138300333357330297291345303138345336324315348120102141102123273135147279183183102342351294315330102030096096027096096096096315306096210315324303138306315324303189120336291348312129102141345363345348303327141342351294315330138342294102123177342303348351342330096348342351303177303330300030096096027096096303330300030027096096342303348351342330096306291324345303030096096096096303330300030096096030096096096096300303306096300303306291351324348285294351315324300285336291297321291309303030096096096096096096291183345303324306138300303306291351324348285315330300303360273144279177096096294183345303324306138300303306291351324348285315330300303360273147279030096096096096096096345303324306138294351315324300285336291297321291309303120291132294123030096096096096303330300030096096030096096096096300303306096327291321303177096096342303348351342330096345303324306138300303306291351324348285294351315324300285336291297321291309303177096096303330300030096096030096096096096105105096294351315324300096291096345333351342297303096336291297321291309303096306315324303096306342333327096315330345348291324324303300096354303342345315333330030096096096096300303306096294351315324300285336291297321291309303096126291342309345096105120315330297324351300303300285306315324303345132315330297324351300303300285300315342285336291348312345123030027096096315330297324351300303300285306315324303345183291342309345273144279030027096096315330297324351300303300285300315342285336291348312345183291342309345273147279030096096096096096096306315324303345285300291348291183273279030027096096327291315330300291348291345303336183102105147105174174105147105174174105144105174174105144105174174105144105102129102174174105147105174174105147105102030027096096306315324303330291327303345303336183102105147105174174105147105174174105144105174174105144105174174105144105102129102174174105144105174174105147105102030027096096306315324303345303336183102105147105174174105147105174174105144105174174105144105174174105144105102129102174174105144105174174105144105102030096096096096096096315330300303360285345303336183102105147105174174105144105174174105144105174174105144105174174105144105102129102174174105102129102144105174174105147105102030027096096105105309303348096315330300303360096306315324303096336291348312345030096096096096096096315330300303360285306315324303345183273279030027096096315330297324351300303300285306315324303345138303291297312096300333096372306372030027096096096096336183306138348333285345138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030027096096096096315330300303360285306315324303345096180180096102141342351294315330141102129336030027096096303330300030027096096105105096324333297291348315333330345096333306096291297348351291324096342303345333351342297303345030027096096330315330297324351300303300285306315324303345183273279030027096096315330297324351300303300285306315324303345138303291297312096300333096372306372030027096096096096336096183096306138348333285345138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030027096096096096330315330297324351300303300285306315324303345096180180096219234249252195228228195252219237234285216207195204207246273147279138348333285345129102141102129336030027096096303330300030027096096315330297324351300303300285306315324303345183330315330297324351300303300285306315324303345030027096096105105309303348096315330300303360096300315342096336291348312345096030027096096315330300303360285300315342345183273279030027096096315330297324351300303300285300315342285336291348312345138303291297312096300333096372300372030027096096096096336183300138348333285345138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030027096096096096315330300303360285300315342345096180180096102141342351294315330141102129336030027096096303330300030096096096096096096105105327291321303096315330300303360096345348342315330309030096096096096096096315330300303360147183315330300303360285306315324303345138318333315330120102189102123030096096096096096096315330300303360150183315330300303360285300315342345138318333315330120102189102123030096096096096096096315330300303360183315330300303360147129102189189102129315330300303360150030027096096105105096309303348096300291348291096333306096291324324096348312303096306315324303345030096096096096096096306315324303345285300291348291183273279030027096096315330297324351300303300285306315324303345138303291297312096300333096372306372030027096096096096306183210315324303138333336303330120306132102342102123177306315324303345285300291348291096180180096306138342303291300096177096096306138297324333345303030027096096303330300030027096096105105297333327294315330303096306315324303345096300291348291096357315348312096348312303315342096315330300303360096336291348312345030027096096330306315324303345285300291348291183273279030027096096306315324303345285300291348291138303291297312096300333096372306300372030027096096096096315183306315324303345285300291348291138315330300303360120306300123030027096096096096336183315330300303360285306315324303345273315138348333285315279030027096096096096300291183102102129336138348333285345129306315324303330291327303345303336129306300138348333285345030027096096096096330306315324303345285300291348291096180180096300291030027096096303330300030027096096030027096096306315324303345336321309096183096330306315324303345285300291348291138318333315330120306315324303345303336123030096096096096096096306315330291324285300291348291096183096327291315330300291348291345303336138348333285345096129096315330300303360138348333285345096129096315330300303360285345303336138348333285345096129096306315324303345336321309138348333285345030027096096306315330291324285300291348291183306315330291324285300291348291138345336324315348120102276330102123138318333315330120102177177102129102177177177102123030027096096300183249267249252207231138300291348291300315342129102141294291297321351336345141315330345348291324324336291297321291309303138348360348102030027096096306096183096210315324303138333336303330120300132102357102123177306138357342315348303120306315330291324285300291348291123177096096306138297324333345303030027030027096096342303348351342330096102267333351342096306315324303096357291345096294351315324348174096102129300138348333285345030030096096096096303330300030096030096096096096105315330345348291324324138315330345348291324324285336291297321291309303120102207174141246351294315330141300291348291141294291297321351336345141315330345348291324324336291297321291309303138348360348102132102201174141255345303342345141147156168144171141204303345321348333336102123030030096096096096300303306096315330345348291324324285336291297321291309303120336291297321291309303132300315342123030096096096096096096315306096345303324306138354303342315306363285315330345348291324324291348315333330285306315324303345120300315342123096183183096348342351303096177096096342291315345303096102246351294315330096315345096291324342303291300363096315330345348291324324303300096348312303342303138102177096096096303330300030096096096096096096315306096210315324303138306315324303189120336291297321291309303123096183183096306291324345303177096096342291315345303096102219330336351348096306315324303096336291348312096315345096315330297333342342303297348138102177096096303330300030027030027096096105105324333291300096300291348291030027096096306183210315324303138333336303330120336291297321291309303132102342102123177096300291348291096183096306138342303291300096177096306138297324333345303030027030027096096105105300303297333300303096300291348291030027096096300291348291183300291348291138345336324315348120102177177177102129102177177102123138318333315330120102276330102123030027030027096096327291315330300291348291345303336183102105147105174174105147105174174105144105174174105144105174174105144105102129102174174105147105174174105147105102030027096096306315324303330291327303345303336183102105147105174174105147105174174105144105174174105144105174174105144105102129102174174105144105174174105147105102030027096096306315324303345303336183102105147105174174105147105174174105144105174174105144105174174105144105102129102174174105144105174174105144105102030096096096096096096315330300303360285345303336183102105147105174174105144105174174105144105174174105144105174174105144105102129102174174105144105174174105147105102030027030027096096300291348291183300291348291138345336324315348120327291315330300291348291345303336123273135147279030030027096096315330300303360285345348342315330309183300291348291138348333285345138345336324315348120315330300303360285345303336123273144279138348333285345030027030027096096306315324303285300291348291183300291348291138345336324315348120315330300303360285345303336123273135147279030030096096096096096096105105336342333297303345345096306315324303345030027096096306315324303285300291348291183306315324303285300291348291138345336324315348120306315324303345303336123030027096096330306315324303285300291348291183273279030027030027096096306315324303285300291348291138303291297312096300333096372300372030027096096096096336183300138345336324315348120306315324303330291327303345303336123273144279030027096096096096300315183300138345336324315348120306315324303330291327303345303336123273147279030027096096096096330306315324303285300291348291180180273336132300315279030027096096303330300030027030027096096306315324303285300291348291183330306315324303285300291348291030027030027096096105336342333297303345096315330300303360030027096096324333291300096102102030027096096306096183096315330300303360285345348342315330309138345336324315348120102189189102123273144279138345336324315348120102189102123030027096096300315096183096315330300303360285345348342315330309138345336324315348120102189189102123273147279138345336324315348120102189102123030030030096096096096096096204315342138327321300315342120300315342138348333285345129102141342351294315330102123030030027096096300315138303291297312096300333096372336372030027096096096096330336183300315342129102141102129336030027096096096096204315342138327321300315342120330336123030027096096303330300030030096096096096096096105096297342303291348303096306315324303345030096096096030096096096096096096306315324303285300291348291138303291297312096300333096372306300372030027096096096096336183300315342138348333285345129102141102129306300273144279138348333285345030027096096096096306183210315324303138333336303330120336132102357102123177096096306138357342315348303120306300273147279138348333285345123177096096306138297324333345303030027096096303330300030030096096096096096096336183300315342138348333285345129102141342351294315330141345363345348303327141342351294315330138342294102030027096096306183210315324303138333336303330120336132102342102123177096096300291348183306138342303291300177096096306138297324333345303030096096096096030096096096096096096333324300285312303291300303342183300291348138345336324315348120102276330102123273144279138345336324315348120102219234249252195228228195252219237234285216207195204207246183102123273135147279030096096096096096096333324300285312303291300303342183303354291324120333324300285312303291300303342138348333285345123030030096096096096096096300291348183300291348138345336324315348120102276330102123273147138138135147279138318333315330120102276330102123030030096096096096096096354303342345315333330183333324300285312303291300303342273150279138348333285345096105105105096306333342096330333357096315348324324096294303096294351309309303300096291330300096357342315348303096348312303096354303342345315333330096291345096348312303096333330303096333306096348312303096315330345348291324324315330309096336291342348363096330333348096348312303096336291297321291309303300132096306315360096324291348303342030096096096096096096312303291300183273102315330345348291324324303300102132300315342129102141342351294315330102132354303342345315333330132252315327303138330333357138348333285345132207234258273102255249207246102279138348333285345132342291330300120171171171171171171171171171171171171171171123138348333285345120153162123279030096096096096096096345348342183102219234249252195228228195252219237234285216207195204207246183102129312303291300138348333285345030027096096030096096096096096096330300291348183345348342129102276330102129300291348030096096096096096096306183210315324303138333336303330120336132102357102123177096096306138357342315348303120330300291348123177096096306138297324333345303030096096096096096096342303348351342330096348342351303096030096096096096303330300030096096030096096096096300303306096345315366303189030096096096096096096306183204315342138327291336120219234249252195228228195252219237234285216207195204207246273147279123273144279030027096096345183144030027096096306138303291297312096300333096372306306372030027096096096096315183210315324303138345315366303189120306306123030027096096096096345096129183096315138348333285315030027096096303330300030027096096342303348351342330096345030096096096096303330300030027030027300303306096309303330303342291348303285315330345348291324324303342030027096096300291348291300315342096183096249267249252207231138300291348291300315342030027096096345303324306138300303306291351324348285294351315324300285336291297321291309303030027096096315306096210315324303138306315324303189120300291348291300315342129102141294291297321351336345141315330345348291324324336291297321291309303138348360348102123030027096096096096315306096210315324303138306315324303189120300291348291300315342129102141345297342315336348345141351330336291297321291309303300285315330345348291324324303342285345297342315336348138342294102123030027027096096030027027096096306096183096210315324303138333336303330120300291348291300315342129102141345297342315336348345141351330336291297321291309303300285315330345348291324324303342285345297342315336348138342294102132102342102123177096345306315324303183306138342303291300177096096306138297324333345303030027027096096306096183096210315324303138333336303330120300291348291300315342129102141294291297321351336345141315330345348291324324336291297321291309303138348360348102132102342102123177096336306315324303183306138342303291300177096096306138297324333345303030096096096096096096096096096096030096096096096096096096096096096345333351342297303096183096102258207246249219237234183117102129258207246249219237234129102117102129345306315324303138345336324315348120102276330102123273153138138135147279138318333315330120102276330102123129102276330102129336306315324303138348333285345030027027096096030027027096096306096183096210315324303138333336303330120300291348291300315342129102141294291297321351336345141342351294315330285315330345348291324324303342138342294102132102357102123177096306138357342315348303120345333351342297303123177096096306138297324333345303030027096096096096096096030027027096096342303348351342330096102267333351342096306315324303096357291345096294351315324348174096102129300291348291300315342129102141294291297321351336345141342351294315330285315330345348291324324303342138342294102030027096096096096303324345303177096096342291315345303096102351330336291297321291309303300285315330345348291324324303342285345297342315336348138342294096357291345096327315345345315330309138102030027027303330300030027096096303324345303177096096342291315345303096102255330291294324303096348333096297342303291348303096291330300096342303291300096315330345348291324324096336291297321291309303138102030027096096303330300030027303330300030027030030027300303306096345330291336345312333348030027096096204315342138315327291309303120249267249252207231138345363345300315342132249267249252207231138300291348291300315342129102141348303327336102132102345363345348303327306315324303345102123030027096096204315342138315327291309303120249267249252207231138297306309300315342132249267249252207231138300291348291300315342129102141348303327336102132102297306309306315324303345102123030027096096204315342138315327291309303120249267249252207231138291336336300315342132249267249252207231138300291348291300315342129102141348303327336102132102291336336306315324303345102123030027096096204315342138315327291309303120249267249252207231138297324291345345300315342132249267249252207231138300291348291300315342129102141348303327336102132102297324291345345306315324303345102123030027096096204315342138315327291309303120249267249252207231138300291348291300315342129102141300303306315330315348315333330345102132249267249252207231138300291348291300315342129102141348303327336102132102300303306315330315348315333330306315324303345102123030027096096096096030027303330300030027030027030027300303306096309303348285312315300300303330285315330348303342330291324285300291348291030027096096354096183096102105216105177105219105177105204105177105204105177105207105177105234105177105219105177105234105102129102177105252105177105207105177105246105177105234105102129102177105261105177105237105177105246105177105204105177105195105177105249105177105249105177105216105102030096096096096096096336291348312096183096249267249252207231138300315342345120102345363345300315342102123096129096102141342351294315330138342294102030096096096096096096315306096210315324303138306315324303189120336291348312123096183183096306291324345303096177096096249267249252207231138303342342333342324333309120102246351294315330138315330345348291324324138309303348285312315300300303330285315330348303342330291324285300291348291174096255330291294324303096348333096324333297291348303096342351294315330138342294099102123096177096096342303348351342330096330315324096177096096303330300030027096096306096183096210315324303138333336303330120336291348312132102342102123096177096096300291348096183096306138342303291300096177096306138297324333345303030027096096312300291348096183096273279030027096096300291348138345336324315348120354123273135147279138345336324315348120102276330102123138303291297312096300333096372324372096177096096324096183096324273150138138135147279030027096096096096315306096324138348333285345096183183096102102096177096330303360348096177096096303330300030027096096096096294303309315330096177096096312300291348096180180096303354291324120324123030027027342303345297351303096177096312300291348096183096174303342342333342096177096096294342303291321030027027303330300030027096096303330300030027096096315306096312300291348096183183096174303342342333342030027096096096096249267249252207231138303342342333342324333309120102246351294315330138315330345348291324324138309303348285312315300300303330285315330348303342330291324285300291348291174096204291348291096327291363096294303096297333342342351336348303300132096315348096297333351324300096330333348096294303096336342333297303345345303300138102123030027027342303348351342330096330315324030027096096303324345303096177096096342303348351342330096312300291348030027096096303330300030027303330300030027030303330300030096096030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105096096297333330348342333324324303342030096096030096096297324291345345096201333330348342333324324303342096096096096096096096096096096105105096354315342348351291324096330303348357333342321096354315291096345312291342303300096357315330300333357345096306333324300303342345030096096300303306096315330315348315291324315366303030096096096096030027105342315309312348096330333357096315330348303342330291324096297333330306315309096315345096315309330333342303300096291330300096345363345348303327096297333330306315309096315345096351345303300138030027192297333330306315309285330291327303345183273102234303348357333342321285204315342303297348333342363102132102234303348357333342321285216333345348102132102255345303342240342315354102279030027192300303306291351324348285297333330306315309183273102102132102102279030027192297333330306315309285300291348291183192300303306291351324348285297333330306315309030027030027192324333309336291348312183249267249252207231138300291348291300315342129102141324333309345141297333330348342333324324303342138348360348102030027030027192297306309336291348312183249267249252207231138300291348291300315342129102141297333330306315309141297333330348342333324324303342138297306309102030096096096096315306096210315324303138306315324303189120192297306309336291348312123096183183096306291324345303177096096345303324306138345291354303285297333330306315309030027303324345303177096096345303324306138324333291300285297333330306315309030027303330300030096096096096030027192297333330348342333324324303342285345348291348303183102315330315348315291324315366303300102030096096096096192294315330300315330309183330315324030096096096096192330303348357333342321285300315342303297348333342363183117117096096096030027192306315324303315333285300315342303297348333342363183249267249252207231138300291348291300315342129102141306315324303315333102030027192294333351330300183306291324345303096096096030027096096096030027192300315342285297324303291330303342285348312342303291300183330315324030030096096303330300030030096096300303306096297324303291330315330309189177096096315306096192300315342285297324303291330303342285348312342303291300096183183096330315324177096096342303348351342330096306291324345303177096096303324345303096177096342303348351342330096192300315342285297324303291330303342285348312342303291300138291324315354303189177096096303330300177096096303330300030030096096300303306096336333345348285315330315348315291324315366303096096105105096306333342096345363345348303327096297333327336333330303330348345096348312303096324333291300303342096357315324324096297312303297321096306333342096348312315345096327303348312333300096291330300096297291324324096315348096315306096363333351096300303306315330303300096315348030096096096096192297333330348342333324324303342285345348291348303096183102336333345348285315330315348315291324315366291348315333330102027030027315306096210315324303138300315342303297348333342363189120249267249252207231138297333330306315309120165123138348333285345123030027096096192330303348357333342321285300315342303297348333342363183249267249252207231138297333330306315309120165123138348333285345030027096096345303324306138345348291342348285327291315330285294315330300315330309030027096096249267249252207231138357342315348303324333309120102246351294315330174174201333330348342333324324303342138336333345348285315330315348315291324315366303174096207354291324294315330300315330309096315345096342351330330315330309132096303354291324174096102129249267249252207231138297333330306315309120171123138348333285345129102132096198333351330300096348333096300315342174102129192330303348357333342321285300315342303297348333342363138348333285345123030027096096315306096108300303294351309177096096336351348345096096102201333330348342333324324303342096102129249267249252207231138315330345348291330297303138315300138348333285345129102096294315330300315330309096300315342303297348333342363174096102129192330303348357333342321285300315342303297348333342363138348333285345177096096303330300030027096096030027303324345315306096249267249252207231138297333330306315309120165123138348333285345183183102102096333342096249267249252207231138297333330306315309120165123096183183096330315324096333342096249267249252207231138297333330306315309120165123138348333285345096183183096102306291324345303102030096096096096096096192330303348357333342321285300315342303297348333342363183102102030027096096249267249252207231138357342315348303324333309120102246351294315330174174201333330348342333324324303342138336333345348285315330315348315291324315366303174096234303348357333342321096300315342303297348333342363096330333348096345303348132096351345315330309096306315324303315333096300315342096294351348096330333348096324291351330297312315330309096303354291324096294315330300315330309138102123030027096096192297333330348342333324324303342285345348291348303096183096102315330291297348315354303102030027096096315306096108300303294351309177096096336351348345096102201333330348342333324324303342096294315330300315330309174096348351342330303300096333306306102177096096303330300030027303324345303030027096096249267249252207231138303342342333342324333309096102246351294315330174174201333330348342333324324303342138336333345348285315330315348315291324315366303174096234303348357333342321096300315342303297348333342363096357291345096315330354291324315300138096267333351096297291330096342303297333330306315309351342303096315348096351345315330309096249267249252207231138297333330306315309120165132117336291348312117123138102027096096030027096096192297333330348342333324324303342285345348291348303096183096102306291315324303300096315330315348102030027096096315306096108300303294351309177096096336351348345096102201333330348342333324324303342096294315330300315330309174096303342342333342102177096096303330300030027303330300030096096096096342303348351342330096330315324030096096303330300030096096030096096300303306096345348291342348285327291315330285294315330300315330309030096096096096315306096192294315330300315330309096099183096330315324177096096342303348351342330096306291324345303177096096303330300030027192294315330300315330309183210315324303219237285207354291324285198315330300303342138330303357120192330303348357333342321285300315342303297348333342363132102303354291324102132348342351303123096096105105096327291363294303096297312291330309303096348312315345096348333096345363345348303327096297333330306315309096165030096096096096192294315330300315330309138345348291342348030027192294333351330300183348342351303030027249267249252207231138357342315348303324333309120102246351294315330174174201333330348342333324324303342138345348291342348285327291315330285294315330300315330309174096201342303291348303300096327291315330096294315330300315330309096333294318303297348138096207354291324174096102129249267249252207231138297333330306315309120171123138348333285345129096102204315342174096102129192330303348357333342321285300315342303297348333342363138348333285345123030027315306096210315324303138306315324303189120192330303348357333342321285300315342303297348333342363129102141297324303291330303342138348291309102123096183183096306291324345303096096105105315306096363333351096312291354303096336342333294324303327345096357315348312096306315324303345096330333348096309303348348315330309096300303324303348303300096318351345348096342351330096348312303096297324303291330303342096348312342303291300096327291330351291324324363096306333342096330333357030027096096345303324306138345336291357330285300315342285297324303291330303342096096030027303324345303030027096096345183210315324303138342303291300120192330303348357333342321285300315342303297348333342363129102141297324303291330303342138348291309102123030027096096315306096345138348333285345183183102102177096345348342183252315327303138330333357135147144144030027096096303324345303177096096345348342183252315327303138345348291327336120345138348333285345123030027096096303330300030027096096348330183252315327303138330333357135345348342030027096096315306096348330138348333285315186171030027096096096096345303324306138345336291357330285300315342285297324303291330303342030027096096303330300030027303330300030096096096096192297333330348342333324324303342285345348291348303096183096102342351330330315330309102030027342303348351342330096348342351303030096096303330300030096096030096096300303306096342351330330315330309189177096096192294315330300315330309138342351330330315330309189177096096303330300030096096030096096300303306096345348333336285327291315330285294315330300315330309030096096096096192294315330300315330309138345348333336177096096192294315330300315330309183330315324177096192345348291348303183102345348333336336303300102030096096303330300030030096096300303306096345336291357330285300315342285297324303291330303342030096096096096315306096192300315342285297324303291330303342285348312342303291300099183330315324177096096342303348351342330096306291324345303177096096303330300027030096096096096192300315342285297324303291330303342285348312342303291300183252312342303291300138330303357369324333333336096300333030027096096294303309315330177096096306183210315324303138333336303330120192330303348357333342321285300315342303297348333342363129102141297324303291330303342138348291309102132102357102123177096096306138357342315348303120252315327303138345348291327336123177096096306138297324333345303177096096342303345297351303177096249267249252207231138303342342333342324333309096102201333330348342333324324303342096297324303291330303342096348312342303291300096306291315324303300096348333096357342315348303096348291309096306315324303138102096177096096303330300030027096096294303309315330096030027027303183273279030027027030027096096096096324183204315342138303330348342315303345120192330303348357333342321285300315342303297348333342363123177096096324138300303324303348303120102138102123177096096324138300303324303348303120102138138102123030096096096096096096096096324138303291297312096369096372354372096303096180180096192330303348357333342321285300315342303297348333342363129102141102129354138348333285345096375027096096030027096096096096303138303291297312096300333096372303303372030027096096096096096096315306096303303138345336324315348120102141102123273135147279273144138138147147279183183102306315324303315333285324315330321135102030027096096096096096096096096306336096183096303303030027027096096096096294303309315330177096096345348342183210315324303138342303291300120306336123030027027096096096096342303345297351303177096096249267249252207231138303342342333342324333309120102246351294315330174174201333330348342333324324303342174096096204315342303297348333342363096297324303291330303342096348312342303291300096312291300096291096342303291300096306291315324351342303096345333096348312303096315348348303342291348315333330096357291345096345321315336336303300138102123177096096330303360348030027027096096096096303330300030027027096096096096345348342150183252315327303138345348291327336120345348342123030027027096096096096348330096183096252315327303138330333357030027027096096096096345303297183348330135345348342150030027027096096096096315306096345303297138348333285306186171030027027096096096096096096315183303303138345336324315348120102141102123273135147279273147150138138135159279030027027096027096096300183303303138345336324315348120102141102123273144138138135150279138318333315330120102141102123030027027096096096096096096306336147183300129102141306315324303315333285315330336351348102129315138348333285345129102138348360348102030027027096096096096096096306336150183300129102141306315324303315333285333351348336351348102129315138348333285345129102138348360348102030027027027096096294303309315330096177096210315324303138300303324303348303120303303123096177096342303345297351303096177177096303330300030027027096096096096096096294303309315330096177096210315324303138300303324303348303120306336147123096177096342303345297351303096177177096303330300030027027096096096096096096294303309315330096177096210315324303138300303324303348303120306336150123096177096342303345297351303096177177096303330300030027027027096096249267249252207231138357342315348303324333309120102246351294315330174174201333330348342333324324303342174096210315324303315333096300303324303348303300096291330096333324300096324315330321174096102129306336138348333285345123030027027096096096096303324345303030027027096096096096303330300027027096096030027096096096096096096303330300030027096096096096303330300030027096096342303345297351303177096096105249267249252207231138303342342333342324333309120102201333330348342333324324303342096300315342096297324303291330303342096348312342303291300096342303345297351303300096291330096351330321330333357330096303342342333342138102123030027096096303330300030027096096345324303303336096159030096096096096303330300375096096096096030096096303330300030030096096300303306096294315330300315330309177096096342303348351342330096192294315330300315330309177096096303330300030096096030096096300303306096327303327294303342345189030096096096096303183204315342138303330348342315303345120192330303348357333342321285300315342303297348333342363123030096096096096303138300303324303348303120102138102123177096096303138300303324303348303120102138138102123030027315306096303138324303330309348312096183183096144096177096096342303348351342330096273279030027303324345303030027096096324183273279030096096096096096096303138303291297312096300333096372303303372030027096096096096105336096183096192330303348357333342321285300315342303297348333342363096129096102141102096129096303303138348333285345030027096096096096315306096303303138300333357330297291345303273144138138147147279096183183096120102306315324303315333285324315330321135102123030027096096096096096096324180180303303138345336324315348120102135102123273135147279138345336324315348120102138102123273144279030027096096096096303330300030027096096303330300030027096096342303348351342330096324030096096096096303330300030096096303330300030096096030096096300303306096357342315348303120315330345348132345348342123030096096096096315306096327303327294303342345189138315330297324351300303189120315330345348138348333285345123030027096096306336183192330303348357333342321285300315342303297348333342363129102141306315324303315333285315330336351348102129315330345348138348333285345129102138348360348102030027096096315306096210315324303138306315324303189120306336123096183183096348342351303030027096096096096294303309315330177096096210315324303138357342315348303120306336132345348342138348333285345123177096342303348351342330096345348342138348333285345138324303330309348312030027027342303345297351303177096096342291315345303096102201333330348342333324324303342096306291315324303300096348333096357342315348303096306315324303174096102129306336138348333285345030027027303330300030027096096303324345303177096096342291315345303096102201333330348342333324324303342096306303300096315330354291324315300096306315324303336291348312174096102129306336138348333285345030027096096303330300030027303324345303177096096342291315345303096102219330354291324315300096315330345348096336291345345303300138102030027303330300030096096303330300030096096030096096300303306096342303291300120315330345348123030096096096096306336183192330303348357333342321285300315342303297348333342363129102141306315324303315333285333351348336351348102129315330345348138348333285345129102138348360348102030027294303309315330177096345348342183210315324303138342303291300120306336123030177027342303345297351303177096342291315345303096102201333330348342333324324303342096342303291300096306291315324303300174096102129306336138348333285345177096345348342183306291324345303030027210315324303138300303324303348303120306336123030027303330300030096096096096342303348351342330096345348342030096096303330300030096096030096096300303306096342303339351303345348120315330345348132345348342123030096096096096315306096210315324303138306315324303189120192330303348357333342321285300315342303297348333342363129102141306315324303315333285333351348336351348102129315330345348138348333285345129102138348360348102123177096210315324303138300303324303348303120192330303348357333342321285300315342303297348333342363129102141306315324303315333285333351348336351348102129315330345348138348333285345129102138348360348102123177096096303330300030096096096096315306096345303324306138357342315348303120315330345348138348333285345132345348342138348333285345123138315345285291189120219330348303309303342123030027096096297183144030027096096342303345096183096330315324030027096096324333333336096300333030027096096096096315306096297186147144177096096342303345183330315324177096096294342303291321177096096303330300030027027315306096210315324303138306315324303189120192330303348357333342321285300315342303297348333342363129102141306315324303315333285333351348336351348102129315330345348138348333285345129102138348360348102123030027027096096342303345183345303324306138342303291300120315330345348138348333285345123030027027096096294342303291321030027027303330300030027027297129183147177096096345324303303336096147030027096096303330300030027096096342303348351342330096342303345030027303324345303177096096342291315345303096102246303339351303345348096306291315324303300096294303297291351345303096201333330348342333324324303342138357342315348303096342291315345303300096291096327303345345291309303138102030096096096096303330300030096096303330300030030096096300303306096315330336351348120315330345348123030096096096096315306096327303327294303342345189138315330297324351300303189120315330345348138348333285345123030027096096306336183192330303348357333342321285300315342303297348333342363129102141306315324303315333285315330336351348102129315330345348138348333285345129102138348360348102030027096096336342315330348102276330102177096096345348342183309303348345138297312333327336030027096096315306096210315324303138306315324303189120306336123096183183096348342351303030027096096096096294303309315330177096096210315324303138357342315348303120306336132345348342138348333285345123177096342303348351342330096345348342138348333285345138324303330309348312030027027342303345297351303177096096342291315345303096102201333330348342333324324303342096306291315324303300096348333096357342315348303096306315324303174096102129306336138348333285345030027027303330300030027096096303324345303177096096342291315345303096102201333330348342333324324303342096306303300096315330354291324315300096306315324303336291348312174096102129306336138348333285345030027096096303330300030027303324345303177096096342291315345303096102219330354291324315300096315330345348096336291345345303300138102030027303330300030096096303330300030030096096300303306096357342315348303324333309120345348342123030096096096096315306096345348342138348333285345138324303330309348312096180183096144177096096342303348351342330096306291324345303177096096303330300030027315306096210315324303138306315324303189120192324333309300315342123096183183096306291324345303177096096306183210315324303138333336303330120192324333309300315342132102357102123177096096306138297324333345303177096096303330300030096096096096348345183252315327303138330333357138348333285345138345336324315348120102096102123273144138138147279138318333315330120102138102123138345336324315348120102174102123138318333315330120102138102123138345336324315348120102135102123138318333315330120102138102123030096096096096306183210315324303138333336303330120192297306309336291348312132102291102123177096306138357342315348303120348345129102174096102129345348342138348333285345123030027342303348351342330096348342351303030096096303330300030030096096300303306096345291354303285297333330306315309030096096096096294303309315330177096096210315324303138357342315348303120192297333330306315309285300291348291138348333285345123030027342303345297351303177096096342303348351342330096306291324345303030027303330300030027342303348351342330096348342351303030096096303330300030096096030096096030096096300303306096324333291300285297333330306315309030096096096096294303309315330177096096192297333330306315309285300291348291183303354291324120210315324303138342303291300120192297306309336291348312123123030096096096096342303345297351303177096096342303348351342330096306291324345303030096096096096303330300030027342303348351342330096348342351303030096096303330300030096096030096096300303306096345348291348303177096096342303348351342330096192297333330348342333324324303342285345348291348303177096096303330300030030096096300303306096324333309177096096342303348351342330096345303324306138294315330300315330309138324333309177096096303330300030030096096300303306096330300315342177096096342303348351342330096345303324306138294315330300315330309138330300315342177096096303330300030096096030096096030030096096297324291345345096210315324303219237285207354291324285198315330300303342096096105105096342303330291327303096348333096297333330348342333324096294315330300315330309030096096096096300303306096315330315348315291324315366303120300315342132327333300303132324333309123096105105096327333300303174096342303291300096141096303354291324030027096096030096096096096096096306336183300315342138348333285345129102141306315324303315333285315330336351348102129249267249252207231138315330345348291330297303138315300138348333285345129102138348360348102030027096096306336150183300315342138348333285345129102141306315324303315333285333351348336351348102129249267249252207231138315330345348291330297303138315300138348333285345129102138348360348102027096030027096096030027096096192300315342183300315342096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096105105294333351330300096300315342030027096096192315330336291348312183306336030027096096192333351348336291348312183306336150030027096096306183210315324303138333336303330120192315330336291348312132102357102123177096096306138297324333345303030027096096030027096096315306096327333300303138348333285345183183102303354291324102177096096192303354291324285291324324333357303300183348342351303177096192327333300303183102303354291324102030027096096303324345315306096327333300303138348333285345183183102342303291300102177096192303354291324285291324324333357303300183306291324345303177096192327333300303183102342303291300102030027096096303330300030027096096030027096096315306096249267249252207231138297333330306315309120171123138348333285345096183183096102348342351303102177096096192303354291324285291324324333357303300183348342351303177096303324345303177096096192303354291324285291324324333357303300096183096306291324345303177096096303330300030027096096192303354291324285315300324303285300303324291363183147138144030027096096192303354291324285300303324291363183144138147030027096096030027096096192324333309183348342351303096096096096096096096096096096105105096342315309312348096330333357096318351345348096333354303342315300303096351330348315324096357303096306315330300096291096294303348348303342096357291363096348333096297333330348342333324096348312315345030027096096192336342315354291348303285324333309183273279030030027096096192330291327303183342291330300120147144144144144144144144144144144144123138348333285345120153162123030027096096192291300327315330183306291324345303096096096030030096096096096096096192345348291348303183117315330315348315291324315366315330309117027096096030027096096192342351330330315330309183306291324345303030027096096192348312342303291300183330315324030027096096192348342291297321303342285348312342303291300183330315324030030027096096192297333330348303360348183249267249252207231096096096105105327291321303096348312315345096291330096315330315348096291342309030027096096192294351306306303342183273279030027096096030027096096192303354291324285348333309309324303183330315324096096096105105030027096096030027096096030027303330300030030096096096096300303306096345348291342348030096096096096096096315306096192342351330330315330309177096096342303348351342330096306291324345303177096096303330300030096096096096096096192342351330330315330309183348342351303177096192345348291348303183102291297348315354303102177096096192333336315300183144030027096096030027096096315306096192327333300303183183102303354291324102030027096096030027096096192348312342303291300183252312342303291300138330303357369030027096096096096324333333336096300333030027096096096096096096315306096192342351330330315330309096183183096306291324345303177096096294342303291321177096096303330300030027027096096192345348291348303183102291297348315354303102030027027096096315306096210315324303138306315324303189120192315330336291348312123096183183096348342351303030096096096096030027096096096096096096096096294303309315330177096096345348342183210315324303138342303291300120192315330336291348312123096096105105348312315345096345312333351324300096306315360096333351342096342291330300333327096291330300096342291342303096303342342333342096120303342342333342174096330333096306315324303096177096297333330348342333324303342138342294096150162165123030027096096096096096096096096342303345297351303177096330303360348096096105105348312303096306315324303096303360315345348345096294351348096297333351324300330348096294303096342303291300096294303297291351345303096315348345096291324342303291300363096333336303330096315330096291330333348312303342096345303345345315333330132096318351345348096345321315336096348312303096342303345348096333306096348312303096324333333336096291330300096297333330348315330351303096330333342327291324324363138030027027027303330300030027027027027030027027027315306096345348342138324303330309348312096186096144096291330300096249267249252207231138297333330306315309120171123138348333285345138300333357330297291345303096183183096102348342351303102030027027027096096030027027027096096192345348291348303183102357333342321315330309102030027027027096096294303309315330177210315324303138357342315348303120192315330336291348312132102102123030027027027096096342303345297351303030027027027096096303330300030027027027096096192294351306306303342180180192333336315300138348333285345129102180180096102129345348342138348333285345030027027027096096030027096096096096096096096096096096315306096192303354291324285291324324333357303300096099183096348342351303096177096345324303303336096192303354291324285315300324303285300303324291363177096096330303360348096177096096303330300030027027027096096030027027027096096294303309315330030027027027096096096096192345348291348303183102303354291324351291348315330309102030027027027096096096096342303345183192297333330348303360348138315330345348291330297303285303354291324120345348342123096096030027027027096096342303345297351303096183186096303030027027027096096096096342303345096183096102207264201207240252219237234174174174096102096129096303138348333285345096129096102276330102096129096303138294291297321348342291297303138318333315330120102276330102123030027027027096096303330300030027027027096096192345348291348303183102336333345348315330309102030027027027096096294303309315330177096096210315324303138357342315348303120192333351348336291348312132342303345138348333285345123030027027027096096342303345297351303030027027027096096303330300030027027027096096345324303303336096192303354291324285300303324291363030027027027096096192294351306306303342096180180096192333336315300138348333285345129102186186096102129342303345138348333285345030027027027096096030027027027096096294303309315330096105105096327291363096306291315324132096327351324348315096315330345348291330297303345096357342315348303096348333096348312303096345291327303096306315324303030027027027096096096096345147183249267249252207231138315330345348291330297303138315300138348333285345129102174102129192333336315300138348333285345129102174102129252315327303138345348291327336030027027027096096096096345150183102180180096102129345348342138348333285345030027027027027345153183102186186096102129342303345138348333285345030027027027027345156183345147129102276330102129345150129102276330102129345153129102276330102030027027027027345159183249267249252207231138315330345348291330297303138315300138348333285345129102174102129192333336315300138348333285345129102174102129252315327303138345348291327336129102174096204315342096324333309096297342303291348303300138096120102129192300315342138348333285345129102123102030027027027096096096096030027027027027315306096192324333309183183348342351303096096105105096321303303336096336030027027027027096096315306096210315324303138306315324303189120192300315342138348333285345129102141324333309138348360348102123096183183096306291324345303030027027027027096096096096306183210315324303138333336303330120192300315342138348333285345129102141324333309138348360348102132102357102123177096096306138357342315348303120345159123177096096306138297324333345303030027027027027096096303330300030027027027027096096306183210315324303138333336303330120192300315342138348333285345129102141324333309138348360348102132102291102123177096096306138357342315348303120345156123177096096306138297324333345303030027027027027096096192336342315354291348303285324333309096180180096345156030027027027027096096345159183345156138345336324315348120102174102123273144138138135147279138318333315330120102174102123030027027027027096096249267249252207231138357342315348303324333309120102210315324303219237135207354291324174096102129345159138348333285345273144138138135150279123030027027027096096096096303330300030027027027027030027027027027105105324333309096348333096345363345348303327096342303309291342300324303345345030027027027027105249267249252207231138357342315348303324333309120102210315324303219237135207354291324174096102129345159138348333285345273144138138135150279123030027027027027105300315345291294324303300096294303297291351345303096291294333354303030027027027027030027027027027105105336342315330348096306315324303315333096315306096297333330306315309351342303300030027027027027315306096249267249252207231138297333330306315309120147144123138348333285345138300333357330297291345303096183183096102348342351303102030027027027027096096336351348345096102276330210315324303219237174102129345156138348333285345030027027027027303330300030027027027027030027027027096096342303345297351303177096096249267249252207231138303342342333342324333309096102201333330348342333324324303342096303354291324096324333309096357342315348303096306291315324303300138102030027027027096096303330300030027027027096096030027027027096096192333336315300096129183096147030027027027096096192345348291348303183102315300324303102177096096345324303303336096192303354291324285315300324303285300303324291363030027027027303324345303177096192345348291348303183102315300324303102177096345324303303336096192303354291324285315300324303285300303324291363030027027027303330300030027096096096096096096303324345303177096096192345348291348303183102315300324303102177096096345324303303336096192303354291324285315300324303285300303324291363030027027096096303330300030027027096096030027096096096096303330300030027096096096096192342351330330315330309183306291324345303177096192345348291348303183102345348333336336303300102030027096096375030027096096030027096096303330300030027096096030027096096345303324306138345336291357330285348342291297321303342285348312342303291300030096096096096096096030027096096342303348351342330096348342351303030027303330300030030027300303306096345336291357330285348342291297321303342285348312342303291300030027096096192348342291297321303342285348312342303291300183252312342303291300138330303357369030027096096096096324333333336096300333030027027096096294303309315330030027096096096096096096096096315306096192342351330330315330309183183306291324345303030027027096096096096303324345303030027027096096096096096096315300183249267249252207231138315330345348291330297303138315300138348333285345030096096096096096096096096096096096096096096306336183192300315342129102141306315324303315333285324315330321135102129315300129102138348360348102030027027096096096096096096306183210315324303138333336303330120306336132102357102123177096096306138357342315348303120252315327303138345348291327336123177096306138297324333345303096030027027096096096096303330300030027096096096096096096096096345324303303336096159138144030027027096096342303345297351303177096105105324333333336096306291315324303300030096096096096096096096096096096303330300027027096096030027096096096096303330300030027096096375030027303330300030027030027030096096096096300303306096345348333336030027096096315306096192342351330330315330309096183183096348342351303030027096096096096192348312342303291300138321315324324177096096192348312342303291300183330315324030027027192348342291297321303342285348312342303291300138321315324324177096192348342291297321303342285348312342303291300183330315324030027027192342351330330315330309183306291324345303030027027342303348351342330096348342351303030027096096303324345303177096096342303348351342330096306291324345303030027096096303330300030027303330300030030030096096096096300303306096324333297321177096096192303354291324285291324324333357303300183306291324345303177096096303330300030027300303306096351330324333297321177096096192303354291324285291324324333357303300183348342351303177096096303330300030027300303306096327333300303096126291342309345030027096096315306096291342309345138324303330309348312096183183096144096177096096342303348351342330096192327333300303030027096096303324345303177096192327333300303096183096291342309345273144279138348333285345030027096096303330300030027303330300030027030096096096096300303306096330300315342177096096342303348351342330096192300315342177096096303330300030027030027300303306096324333309177096342303348351342330096192336342315354291348303285324333309177096096303330300030096096030096096096096300303306096342351330330315330309189177096096342303348351342330096192342351330330315330309177096096303330300030027030027300303306096303354291324189177096096315306096345303324306138342351330330315330309189096291330300096249267249252207231138297333330306315309120171123096291330300096192303354291324285291324324333357303300177096342303348351342330096348342351303177096096303324345303177096342303348351342330096306291324345303177096096303330300177096096303330300030027030096096096096303330300030096096030096096303330300030030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105030096096030096096297324291345345096234303348357333342321285231291330291309303342030096096096096105105030027105030027105030027300303306096315330315348315291324315366303030096096096096303330300030096096096096300303306096336333345348285315330315348315291324315366303030096096096096303330300030027030027027030027300303306096345312351348300333357330177096096177096096303330300030096096303330300030096096030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105030096096030096096297324291345345096246351294363285231291330291309303342030096096096096300303306096315330315348315291324315366303030096096096096096096105192297306309336291348312183249267249252207231138297306309300315342129102141342351294363138297306309102030096096096096030027096096192300303306291351324348285297333330306315309183273279030027096096192297333330306315309183192300303306291351324348285297333330306315309030096096096096096096105345303324306138324333291300285297333330306315309030096096096096096096105192342351294363300315342183345303324306138324333297291348303285312333345348285342351294363030096096030096096096096303330300030030096096096096300303306096342351294363300315342177342303348351342330096192342351294363300315342177303330300030030096096096096300303306096324333291300285297333330306315309030096096096096096096315306096210315324303138306315324303189120192297306309336291348312123030027096096096096294303309315330177300183210315324303138342303291300120192297306309336291348312123177300183303354291324120300123177192297333330306315309183300030027096096096096342303345297351303177105249267249252207231138303342342333342324333309120102246351294363096201333330306315309096297333351324300096330333348096294303096324333291300303300132096315348096327315309312348096294303096297333342342351336348303300138102123030027096096096096303330300030027096096303324345303177105249267249252207231138303342342333342324333309120102246351294363096201333330306315309096357291345096327315345345315330309132096315348096312291300096294303096342303345348333342303300138102123030027096096096096306183210315324303138333336303330120192297306309336291348312132102357102123177306138357342315348303120192300303306291351324348285297333330306315309138348333285345123177306138297324333345303030027096096303330300096096030096096096096303330300030096096030096096096096300303306096345291354303285297333330306315309030096096096096096096030096096096096303330300030027030096096303330300030096096030096096105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030096096105105096303330300096333306096303327294303300300303300096297324291345345303345030303330300096096105105096303330300096333306096348312303096327291345345315354303096246351294315330249363345348303327096297324291345345030030249267249252207231183246351294315330249363345348303327138330303357096096096096096096096096105105096297342303291348303096345363345348303327096297324291345345030249267249252207231138336333345348285315330315348315291324315366303096096096096105105096297342303291348303096345363345348303327096333294318303297348345030249267249252207231138345348291342348351336096096096096096096096096096096096096096096096096105105096342351330096291351348333345348291342348096291336336345141345297342315336348345030030105216105177105219105177105204105177105204105177105207105177105234105177105219105177105234105177105252105177105207105177105246105177105234105177105261105177105237105177105246105177105204105177105195105177105249105177105249105177105216105030105105273273102141291336336102132102141297324291345345102132102141300291348291102132102141345312333342348297351348345102132102141300291348291141291336336300291348291102132102141300291348291141297333330306315309102132102141300291348291141324333309345102132102141300291348291141351345303342102132102141300291348291141300303306315330315348315333330345102132102141300291348291141306315324303315333102132102141300291348291141294291297321351336345102132102141300291348291141348303327336102132102141300291348291141345363345102132102141300291348291141345363345141315330345348291330297303102279132273279279030105105273273102108345363345300315342102132102141345363345348303327102279132096273102108291336336300315342102132102141291336336102279132096273102108297324291345345300315342102132102141297324291345345102279132096273102108300291348291300315342102132102141300291348291102279132096273102108291336336300291348291300315342102132102141300291348291141291336336300291348291102279132096273102108297306309300315342102132102141300291348291141297333330306315309102279132096273102108324333309300315342102132102141300291348291141324333309345102279132096273102108351345303342300315342102132102141300291348291141351345303342102279132096273102108294315330300315342102132102141294315330102279279030105105030105105"], ["/rubin/system/daemond.rb", "3105096105105096252312315345096306315324303096297333330348291315330345096291351348333327291348315297096345363345348303327096345303342354315297303345096291330300096315345096342351330096291351348333327291348315297291324324363096294363096204291303327333330300096357312303330096336333345348285315330315348096315345096342351330030030105105234195231207183219234249252195234201207285231195234195213207231207234252030105105240195246207234252183204195207231237234204030324333333336096300333030096096105105297342303291348303096315330345348291330297303096348291309096294363096357342315348315330309096348312303096348315327303096315330096291096306315324303096348333096345312333357096357303096291342303096342351330330315330309030096096096096294303309315330030096096096096096096096096096096306336183249267249252207231138300291348291300315342129102141345363345141315330345348291330297303141102129219234249252195234201207138348333285345129102138300291348102030096096096096096096096096096096306183210315324303138333336303330120306336132102357102123177306138357342315348303120252315327303138345348291327336123177306138297324333345303030096096096096096096096096096096105105345297291330096291324324096315330345348291330297303096306315324303345096291330300096342303327333354303096291330363096291294291330300333330303300096315330345348291330297303345120297324315297321315330309096297324333345303096357315348312096333351348096345312351348348315330309096300333357330096333342096345333327303096333348312303342096291294342351336348096303360315348123030096096096096096096096096096096315183204315342138303330348342315303345120249267249252207231138300291348291300315342129102141345363345141315330345348291330297303102123177096315138300303324303348303120102138102123177096315138300303324303348303120102138138102123030096096096096096096096096096096315306096315138324303330309348312186144030096096096096096096096096096096096096315138303291297312096300333096372315315372030027027027096096030027027027096096315306096315315096099183096219234249252195234201207096030027027027096096030096027096096096096096096096096096096306336183249267249252207231138300291348291300315342129102141345363345141315330345348291330297303141102129315315030027096096096096096096096096096096345348342183210315324303138342303291300120306336123030027096096096096096096096096096096315306096345348342138324303330309348312183183144030027096096096096096096096096096096096096210315324303138300303324303348303120306336123027030027096096096027096096096096096096096096249267249252207231138357342315348303324333309120102246351294315330174174204291303327333330300174096237351348300291348303300096291330300096297333342342351336348303300096315330345348291330297303096306315324303096342303327333354303300138096120102129315315138348333285345129102123102123030027096096096096096096096096096096303324345303030027096096096096096096096096096096096096345348291327336183252315327303138345348291327336120345348342123096096096096096105105096204207240207234204195234201267096333330096300303306315330315348315333330345096252315327303096297324291345345096351336300291348303030027096096096096096096096096096096096096345303297183252315327303138330333357135345348291327336030027096096096096096096096096096096096096315306096345303297138348333285315186147159030027096096096096096096096096096096096096096096210315324303138300303324303348303120306336123027030027027096096096096096096096096096096249267249252207231138357342315348303324333309120102246351294315330174174204291303327333330300174096237351348300291348303300096315330345348291330297303096306315324303096342303327333354303300138096120102129315315138348333285345129102096177096102129345348342138348333285345129102096123102123030027096096096096096096096096096096096096303330300030027096096096096096096096096096096303330300030027027096096030027027096096096096096096303330300030027027096096030027096096096096096096096096303330300030096096096096096096096096096096303330300030096096096096096096096096342303345297351303177105096249267249252207231138303342342333342324333309096102219330345348291330297303096351336300291348303096348312342303291300096312291300096291096357342315348303096306291315324351342303138102030096096096096096096096096303330300030096096096096096096096096345324303303336096192300291303327333330300285300303324291363138348333285306030303330300030027027030105105246207231237258207252216219249249252246219234213105177105105105177105105105177105105105177105105105030030"], ["/rubin/system/definitions.rb", "3105345303324306138342294105159105177105162105177105171105177105171105177105156105177105159105177105162105177105165105177105171105177105162105177105156105105105096345303324306138342294030030105096195228240216195198207252219201096201216195246195201252207246249030195228240216195183096273102291102132102294102132102297102132102300102132102303102132102306102132102309102132102312102132102315102132102318102132102321102132102324102132102327102132102330102132102333102132102336102132102339102132102342102132102345102132102348102132102351102132102354102132102357102132102360102132102363102132102366102279030105096195228240216195234255231207246219201096201216195246195201252207246249030195228240216195234255231096183096273102291102132102294102132102297102132102300102132102303102132102306102132102309102132102312102132102315102132102318102132102321102132102324102132102327102132102330102132102333102132102336102132102339102132102342102132102345102132102348102132102351102132102354102132102357102132102360102132102363102132102366102132102144102132102147102132102150102132102153102132102156102132102159102132102162102132102165102132102168102132102171102279030105105096195249201219219096201216195246195201252207246249030201216195246249096183096273279096177096297096183096144096177096150159162138348315327303345369096201216195246249096180180096297138297312342138348333285345096177096297096129183096147096375030105105096249267231198237228096201216195246195201252207246249030030105105096303354303342363096168096294315348096294315330291342363096330351327294303342096315330096297291342300315330291324096333342300303342030198219234195246267096183096273279096177096297096183096144096177096150159162138348315327303345096369096096294096183096297138348333285345120150123096177096351330348315324096294138348333285345138324303330309348312096183183096168096177096294096183096102144102096129096294138348333285345096177096303330300096177096198219234195246267096180180096294096177096297096129183096147096375030030105105096303354303342363096312303360315297300303315327291324096330351327294303342096315330096333342300303342030216207264096183096273279096177096297096183096144096177096150159162138348315327303345096369096312096183096297138348333285345120147162123096177096315306096312138324303330309348312096183183096147096177096312096183096102144102096129096312138348333285345096177096303330300096177096216207264096180180096312096177096297096129183096147096375030105105096291096324315345348096333306096291324324096168096294315348096294363348303096297333300303345096306333342096348312303096291345297315315096297312291342291297348303342345030105198267252207249096183096273279096177096216207264138303291297312096300333096372312372096177096198267252207249096180180096102360102096129096312096177096303330300030030105105345363345348303327141342303309315333330096348303342327333330333324333309363030204195267249096183096273102345351330300291363102132102327333330300291363102132102348351303345300291363102132102357303300330303345300291363102132102348312351342345300291363102132102306342315300291363102132102345291348351342300291363102279030231237234252216249096183096273102318291330351291342363102132102306303294342351291342363102132102327291342297312102132102291336342315324102132102327291363102132102318351330303102132102318351324363102132102291351309351345348102132102345303336348303327294303342102132102333297348333294303342102132102330333354303327294303342102132102300303297303327294303342102279030249207195249237234249096183096273102345336342315330309102132102345351327327303342102132102291351348351327102132102357315330348303342102279030105096246255198267096225207267261237246204249030225207267261237246204249096183096273102291324315291345102132096102291330300102132096102294303309315330102132096102294342303291321102132096102297291345303102132096102297324291345345102132096102300303306102132096102300303306315330303300189102132096102300333102132096102303324345303102132096102303324345315306102132096102303330300102132096102303330345351342303102132030096096096096096096096096096096096096102306291324345303102132096102306333342102132096102315306102132096102315330102132096102327333300351324303102132096102330303360348102132096102330315324102132096102330333348102132096102333342102132096102342303300333102132096102342303345297351303102132096102342303348342363102096102342303348351342330102132096102345303324306102132030027027027102345351336303342102132096102348312303330102132096102348342351303102132096102351330300303306102132096102351330324303345345102096102351330348315324102132096102357312303330102132096102357312315324303102132096102363315303324300102132096102324333333336102279030105096246255198267096237240207246195252237246249030237240207246195252237246249096183096273102129102132096102135102132096102126102096132102141102132096102111102132096102126126102132096102183183102132096102099183102132096102186102132096102186183102132096102180102132096102180183102132096102180183186102132096102183183183102132096102138303339324189102132096102303339351291324189102132096102099378102132030096096096096096096096096096096096096096102183378102132096102114102132096102372102132096102282102132096102378102132096102114114102132096102372372102279030105096246255198267096204195252195096252267240207249030204195252195252267240207249096183096273102234351327303342315297102132096102219330348303309303342102132096102210324333291348102132096102198315309204303297315327291324102132096102246291348315333330291324102132096102201333327336324303360102132096102249348342315330309102132096102249363327294333324102132096102195342342291363102132096102216291345312102132030096096096096096096096096096096096096096102246291330309303102132096102246303309303360336102132096102252315327303102132096102204291348303102132096102204291348303252315327303102132096102252342351303201324291345345102132096102210291324345303201324291345345102132096102234315324201324291345345102279030030105096213228237198195228096228219234225249096252237096204195252195030108195228240216195096183096195228240216195030108195228240216195234255231096183096195228240216195234255231030108201216195246249096183096201216195246249030108198219234195246267096183096198219234195246267030108216207264096183096216207264030108204195267249096183096204195267249030108231237234252216249096183096231237234252216249030108249207195249237234249096183096249207195249237234249030108225207267261237246204249096183096225207267261237246204249030108237240207246195252237246249096183096237240207246195252237246249030108204195252195252267240207249096183096204195252195252267240207249030030030300303306096294303330297312327291342321303300285324333291300120345297342315336348123030096096351330324303345345096210315324303138306315324303189120345297342315336348123177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030096096294303309315330030096096096096348147096183096252315327303138330333357030096096096096324333291300120345297342315336348123030096096096096348150183252315327303138330333357030096096096096342303348351342330096348150135348147030096096342303345297351303096183186096303177096096342303348351342330096102207360297303336348315333330174096102129303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123129102276330102030096096303330300030303330300030030030300303306096294303330297312327291342321303300285303354291324120345297342315336348123030096096351330324303345345096345297342315336348138315345285291189120249348342315330309123096291330300096345297342315336348138348333285345138324303330309348312096186096144177096096342291315345303096102219330354291324315300096291342309351327303330348132096345312333351324300096294303096249348342315330309138102177096096303330300030096096294303309315330030096096096096348147096183096252315327303138330333357030096096096096303354291324120345297342315336348138348333285345123030096096096096348150096183096252315327303138330333357030096096096096342303348351342330096348150135348147030096096342303345297351303096183186096303177096096342303348351342330096102207360297303336348315333330174096102129303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123129102276330102030096096303330300030303330300030030030105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105030105105096348312315345096345348351306306096315345096306333342096333294318303297348345096348312291348096330303303300096348312303315342096336291342303330348096297324291345345096348333096312291354303096291096327303348312333300096333342096291324315291345096330291327303132096297324291345345096333342096333348312303342096333294318303297348345030105105096294291345315297291324324363096348312303096345348351306306096363333351096300303306315330303096312303342303096315345096315330096348312303096297333330348303360348096333306096303354303342363096297324291345345096333294318303297348030237294318303297348138297324291345345285303354291324369030096096300303306096324333297291324285327303348312333300345096177096327345096183096345303324306138327303348312333300345096177096327303348345096183096273279096177096327345138303291297312096369096372327372096327303348345096180180096327138348333285345096375096177096342327096183096345303324306138297324291345345138327303348312333300345096177096345303324306138297324291345345138297324291345345138327303348312333300345138303291297312096369096372327372096342327096180180096327138348333285345096375096177096330327096183096273279096177096327303348345138303291297312096369096372327372096351330324303345345096342327138315330297324351300303189120327138348333285345123096177096330327096180180096327138348333285345096177096303330300096375096177096342303348351342330096330327096177096303330300030096096291324315291345096174327096174327303348312333300345096177096291324315291345096174324327096174324333297291324285327303348312333300345030096096291324315291345096174324354096174324333297291324285354291342315291294324303345096177096291324315291345096174309354096174309324333294291324285354291342315291294324303345096177096291324315291345096174315354096174315330345348291330297303285354291342315291294324303345030096096291324315291345096174315354345096174315330345348291330297303285354291342315291294324303285345303348096177096096096291324315291345096174315354309096174315330345348291330297303285354291342315291294324303285309303348096096096105105300333330348096306333342309303348096309303348141345303348096297333330345348291330348345096291330300096297324291345345354291342315291294324303345030096096291324315291345096174315303354096174315330345348291330297303285303354291324096177096291324315291345096174303354096174303354291324030096096300303306096297333330345348291330348345096177096345303324306138297324291345345138297333330345348291330348345096177096303330300096177096291324315291345096174297330096174297333330345348291330348345030096096030096096300303306096309303348345285303354291324096126291342309345096105105327351324348315324315330303096297333330345333324303096315330336351348096348303342327315330291348303300096357315348312096369303330300375030096096096096324315330303345183273279030096096096096315306096291342309345138324303330309348312183183147177297333330348183291342309345273144279177096096303324345303177096096297333330348183345303324306177096096303330300030096096096096324333333336096300333030096096096096096096324315330303183309303348345138297312333327336030027096096315306096324315330303138348333285345183183102369303330300375102177096096294342303291321030027096096303324345303177096096324315330303345096180180096324315330303138348333285345030027096096303330300030096096096096303330300030096096096096297333300303183324315330303345138318333315330120102276330102123129102276330102030096096096096294303309315330177096096342303345096183096297333330348138315330345348291330297303285303354291324120297333300303123030096096096096342303345297351303096183186096303177096096342303345183303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123030096096096096303330300030096096096096342303348351342330096342303345030096096303330300030096096096096030096096030096096105105096324333309315297096333336303342291348333342345096294363096330291327303030096096300303306096285291330300120291132294123096177096315306096291096183183096147096291330300096294096183183096147096177096342303348351342330096147096177096303324345303096177096342303348351342330096144096177096303330300096177096303330300030096096300303306096285333342120291132294123096177096315306096291096183183096144096291330300096294096183183096144096177096342303348351342330096144096177096303324345315306096291096183183096147096291330300096294096183183096147096177096342303348351342330096147096177096303324345303096177096342303348351342330096147096177096303330300096177096303330300030096096300303306096285330333348120291132294123096177096315306096291096183183096144096291330300096294096183183096144096177096342303348351342330096147096177096303324345303096177096342303348351342330096144096177096303330300096177096303330300030096096300303306096285330333342120291132294123096177096315306096291096183183096144096291330300096294096183183096144096177096342303348351342330096147096177096303324345303096177096342303348351342330096144096177096303330300096177096303330300030096096300303306096285330291330300120291132294123096177096315306096291096183183096147096291330300096294096183183096147096177096342303348351342330096144096177096303324345303096177096342303348351342330096147096177096303330300096177096303330300030096096300303306096285360333342120291132294123096177096315306096291096183183096144096291330300096294096183183096144096177096342303348351342330096144096177096303324345315306096291096183183096147096291330300096294096183183096147096177096342303348351342330096144096177096303324345303096177096342303348351342330096147096177096303330300096177096303330300030030030096096105105096342291330300333327096291324336312291330351327303342315297096345348342315330309096333306096300303348303342327315330303300096324303330309348312096030096096300303306096342291330300345120324303330309348312132096330333330351327294303342345183306291324345303123030096096096096315306096324303330309348312138348333285315096180096147177096096342291315345303096102219330354291324315300096291342309351327303330348138102177096096303330300030096096096096345348342096183096273279030096096096096315306096330333330351327294303342345096183183096306291324345303177096096324303330309348312138348315327303345096369096345348342180180120108195228240216195234255231138345312351306306324303123273144279096375030096096096096303324345303177096096324303330309348312138348315327303345096369096345348342180180120108195228240216195138345312351306306324303123273144279096375096030096096096096303330300030096096096096342303348351342330096345348342138318333315330120117117123030096096303330300030030030096096300303306096312333345348189096096105105096348312303345303096291342303096324291315300096333351348096306333342096327333342303096297333327336324315297291348303300096297312303297321345096324291348303342030096096096096312333345348096183096117117030096096096096315306096210315324303138300315342303297348333342363189120102201174141102123096291330300096207234258273102237249102279096183183096102261315330300333357345285234252102030096096096096096096312333345348096183096102261315330300333357345102030096096096096303324345315306096210315324303138300315342303297348333342363189120102141312333327303102123030096096096096096096312333345348096183096102228315330351360102030096096096096303324345303030096096096096096096312333345348096183096306291324345303030096096096096303330300030096096096096342303348351342330096312333345348030096096303330300030030030096096300303306096315330348303342330303348189096096105105096348342363096348333096255246219096309333333309324303030096096096096294303309315330030177096096096096096096351342315096183096255246219138333336303330120102312348348336174141141357357357138309333333309324303138297333327102123030096096096096096096297333330348096183096351342315138342303291300030096096096096096096315306096297333330348138324303330309348312096183183096144177096096342291315345303096102234333096297333330348303330348096315330297324351300303300096315330096342303345336333330345303138102177096096303330300030027096096342303348351342330096348342351303030096096096096342303345297351303096183186096303177096096342303348351342330096303030096096096096303330300030096096303330300030096096030096096030375105168105177105153105177105159105177105153105177105147105177105168105177105153105177105159105177105153105177105168105177105159105105291342342291363138342294105159105177105162105177105171105177105171105177105156105177105159105177105162105177105165105177105171105177105162105177105156105105105291342342291363138342294030195342342291363138297324291345345285303354291324369030030030375105168105177105153105177105159105177105153105177105147105177105168105177105153105177105159105177105153105177105168105177105159105105300315342138342294105159105177105162105177105171105177105171105177105156105177105159105177105162105177105165105177105171105177105162105177105156105105300315342138342294030204315342138315330345348291330297303285303354291324369030030096096300303306096303360315345348189096315330336096105105096303360315345348096315330096300315342096345312333351324300096324315330321096348333096210315324303138303360315345348189096345315330297303096315348096297312303297321345096294333348312096306315324303345096291330300096096300315342345030096096096096210315324303138303360315345348189120315330336123030096096303330300030030030096096300303306096300315342096126291342309345096105105096309303348345141345303348345096357333342321300315342030096096096096315306096291342309345138324303330309348312183183144177342303348351342330096204315342138309303348357300138348333285345030096096096096303324345315306096291342309345273144279138315345285291189120249348342315330309123030096096096096096096315306096210315324303138300315342303297348333342363189120291342309345273144279123096177096204315342138297312300315342120291342309345273144279123096177096342303348351342330096204315342138309303348357300138348333285345030096096096096096096303324345315306096210315324303138300315342303297348333342363189120204315342138309303348357300138348333285345096129096102141102096129096291342309345273144279138348333285345123096177096204315342138297312300315342120204315342138309303348357300138348333285345096129096102141102096129096291342309345273144279138348333285345123096177096342303348351342330096204315342138309303348357300138348333285345030027096096303324345303096177096342291315345303096102234333096345351297312096300315342303297348333342363138102030096096096096096096303330300030096096096096303330300030096096303330300030096096030096096300303306096354315303357096126291342309345096105105096336342315330348345096300315342303297348333342363096297333330348303330348345096348333096345297342303303330030096096096096315306096291342309345273144279096183183096330315324030027096096300315342096183096204315342138309303348357300138348333285345030096096096096303324345315306096210315324303138300315342303297348333342363189120291342309345273144279138348333285345123030096096096096096096300315342096183096291342309345273144279138348333285345096096030096096096096303324345315306096210315324303138300315342303297348333342363189120204315342138309303348357300096129096291342309345273144279123030096096096096096096300315342096183096204315342138309303348357300096129096291342309345273144279030096096096096303324345303030096096096096096096300315342096183096306291324345303030096096096096303330300030096096096096315306096300315342096183183096306291324345303096177096342291315345303096102234333096345351297312096300315342303297348333342363174096102096129096291342309345273144279138348333285345030096096096096303324345303096030027096096096096297333330348096183096204315342138303330348342315303345120300315342138348333285345123096177096297333330348138300303324303348303120102138102123096177096297333330348138300303324303348303120102138138102123096177096294348096183096144030027027315306096297333330348138324303330309348312096183183096144096177096342303348351342330096096102204315342303297348333342363096315345096303327336348363102096030027096096096096303324345303030027027096096345348342096183096273279096177096306315096183096273279096177096306333096183096273279030027027096096297333330348138303291297312096300333096372336372030027027096096096096315306096210315324303138306315324303189120300315342138348333285345096129096102141102096129096336138348333285345123030027027096096096096096096096096096096096096096096294303309315330096177096345096183096210315324303138345315366303189120300315342138348333285345096129096102141102096129096336138348333285345123138348333285345096177096342303345297351303096177096345096183096102102096177096303330300030027027027096096306315096180180096102210315324303174096102096129096336138348333285345096129096102096096096096249315366303174096102096129096345138348333285345030027027096096096096303324345315306096210315324303138300315342303297348333342363189120300315342138348333285345096129096102141102096129096336138348333285345123030027027027096096306333096180180096102204315342174096096102096129096336138348333285345096129096102102030027027027303330300030027027096096303330300030027027096096345348342096180180096102204315342303297348333342363174096096096276102102096129096300315342138348333285345096129096102276102096096096210315324303345174096102096129096306315138324303330309348312138348333285345096129096102132096210333324300303342345174096102096129096306333138324303330309348312138348333285345030027027096096345348342096180180096102105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105102030027027096096306333138303291297312096369096372306372096345348342096180180096306138348333285345096375096177096306315138303291297312096369096372306372096345348342096180180096306138348333285345096375030027027096096345348342096180180096102105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105276330102030027027096096336351348345096345348342138318333315330120102276330102123138348333285345030027027303330300030096096096096303330300030096096303330300030096096030096096030096096300303306096327291336120300315342123030096096096096300315342096183096210315324303138318333315330120204315342138309303348357300132096300315342123096351330324303345345096210315324303138300315342303297348333342363189120300315342123096030096096096096297351342096183096330315324177096096342303327096183096273300315342279030096096096096306315096183096273279177096096306333096183096273279177096096303360096183096273279030096096096096351330348315324096342303327138303327336348363189030096096096096096096297351342096183096342303327138345312315306348030096096096096096096105336351348345096102240342333297303345345315330309174096102129297351342138348333285345027096096030096096096096096096294303309315330030096096096096096096096096204315342138306333342303291297312120297351342123096369096372336372030096096096096096096096096096096330303360348096315306096336096183183096117138117096372372096336096183183096117138138117030096096096096096096096096096096336291348312096183096210315324303138318333315330120297351342132096336123030096096096096096096096096096096315306096210315324303138345348291348120336291348312123138306315324303189177096096306315138336351345312120336291348312123030027027096096096096105336351348345096102204315345297333354303342303300096306315324303174096102129336291348312138348333285345030096096096096096096096096096096303324345315306096210315324303138345348291348120336291348312123138300315342303297348333342363189177096096306333138336351345312120336291348312123177096096342303327138336351345312120336291348312123030027027096096096096105336351348345096102204315345297333354303342303300096300315342174096102129336291348312138348333285345030096096096096096096096096096096303330300030027027375030096096096096096096342303345297351303177096096303360138336351345312120297351342123030027096096096096105336351348345096102210195219228207204174096102129297351342138348333285345030096096096096096096303330300030027096096105336351348345096102240342333309342303345345174096102030027096096105336351348345096102204315342345174096102129306333138324303330309348312138348333285345096129096102132096210315324303345174096102129306315138324303330309348312138348333285345030027096096105336351348345096102246303327291315330315330309096300315342345174096102129342303327138324303330309348312138348333285345030096096096096303330300030096096096096315306096303360138303327336348363189177096096342303348351342330096273306315132096306333279030096096096096303324345303177096096342303348351342330096273306315132096306333132096303360279030096096096096303330300030096096096096342303345297351303096207342342330333174174207234237252204219246177096096102195342309351327303330348096315345096291096306315324303138102030096096096096342303345297351303096207342342330333174174207234237207234252177096096342291315345303096102234333096345351297312096300315342303297348333342363102030096096303330300030030096096030096096300303306096345315366303189120300315342123030096096096096342291315345303096102234333096345351297312096306315324303096333342096300315342303297348333342363138102096351330324303345345096210315324303138303360315345348189120300315342123030096096096096342291315345303096102105369300315342375096315345096291096306315324303138096345315366303189096342303348351342330345096348312303096345315366303096333306096300315342303297348333342315303345132096330333348096306315324303345138102096315306096210315324303138306315324303189120300315342123030096096096096348333348291324285345315366303096183096144030096096096096204315342138309324333294120210315324303138318333315330120300315342132096117126126117132096117126117123123138303291297312096300333096372336291348312372030096096096096096096348333348291324285345315366303096129183096210315324303138345315366303120336291348312123096315306096210315324303138306315324303189120336291348312123030096096096096303330300030096096096096348333348291324285345315366303030096096303330300030096096030096096300303306096303327336348363189120300315342123030096096096096342291315345303096102234333096345351297312096306315324303096333342096300315342303297348333342363138102096351330324303345345096210315324303138303360315345348189120300315342123030096096096096342291315345303096102105369300315342375096315345096291096306315324303138096303327336348363189096342303348351342330345096348342351303096306333342096303327336348363096300315342303297348333342315303345132096330333348096306315324303345138102096315306096210315324303138306315324303189120300315342123030096096096096120204315342138303330348342315303345120300315342123096135096111357273138096138138279123138303327336348363189030096096303330300030096096030030030096096300303306096303327336348363099120300315342123030096096096096306291315324303300096183096273279030096096096096204315342138309324333294120102105369300315342375141126102123138303291297312096300333096372336291348312372030096096096096096096294303309315330030096096096096096096096096315306096210315324303138306315324303189120336291348312123177096096210315324303138300303324303348303120336291348312123030096096096096096096096096303324345315306096210315324303138300315342303297348333342363189120336291348312123177096096303327336348363099120336291348312123177096096204315342138300303324303348303120336291348312123030096096096096096096096096303330300030096096096096096096342303345297351303096183186096303177096096306291315324303300096180180096273336291348312132096102105369303138327303345345291309303375102279030096096096096096096303330300030096096096096303330300030096096096096315306096306291315324303300138303327336348363189177096096342303348351342330096096348342351303030096096096096303324345303177096096342303348351342330096306291315324303300030096096096096303330300030096096303330300030030030096096300303306096300303324303348303099120300315342123030096096096096315306096345303324306138303327336348363189120300315342123177096096345303324306138300303324303348303120300315342123177096096342303348351342330096348342351303030027303324345303030027096096315306096345303324306138303327336348363099120300315342123177096096204315342138300303324303348303120300315342123177096096342303348351342330096348342351303030027096096303324345303177342303348351342330096306291324345303030027096096303330300030027303330300030096096303330300030030096096300303306096297333336363120300315342132330303357300315342123096105105096297333336363096351348315324315348363030096096096096315306096210315324303138300315342303297348333342363189120300315342123030096096096096096096315306096210315324303138300315342303297348333342363189120330303357300315342138348333285345096129096102141102096129096300315342138348333285345138345336324315348120102141102123273135147279138348333285345123096183183096306291324345303030027096096096096327096183096204315342138327291336120300315342138348333285345123030027027315306096327096183183096273273279132273279279030027027096096204315342138327321300315342120330303357300315342138348333285345096129096102141102096129096300315342138348333285345138345336324315348120102141102123273135147279138348333285345123030027027303324345303096177096204315342138327321300315342120330303357300315342138348333285345096129096102141102096129096300315342138348333285345138345336324315348120102141102123273135147279138348333285345123030027027096096315306096327273147279138324303330309348312096186096144030027027096096096096327273147279138303291297312096300333096372300372030027027027096096330300096183096330303357300315342138348333285345096129096102141102096129096300138348333285345138345336324315348120300315342138348333285345123273147279138348333285345030027027027096096204315342138327321300315342120330300138348333285345123030027027027303330300030027027096096303330300030027027096096315306096327273144279138324303330309348312096186096144030027027096096096096327273144279138303291297312096300333096372336372030027027027096096306315096183096210315324303138333336303330120336138348333285345132102342102123096177096297333330348096183096306315138342303291300138348333285345096177096306315138297324333345303030027027027096096330336096183096330303357300315342138348333285345096129096102141102096129096336138348333285345138345336324315348120300315342138348333285345123273147279138348333285345030027027027096096306315096183096210315324303138333336303330120330336138348333285345132102357102123096177096306315138357342315348303120297333330348138348333285345123096177096306315138297324333345303030027027027303330300030027027096096303330300030027027303330300030027096096096096342303348351342330096348342351303030027096096303324345303096177096342303348351342330096102252291342309303348096300315342303297348333342363096291324342303291300363096297333330348291315330345096291096300315342303297348333342363096357315348312096348312303096345291327303096330291327303096291345096348312303096333330303096363333351117342303096297333336363315330309138102030027096096303330300030027303324345303096177096342303348351342330096102234333096345351297312096300315342303297348333342363138102030027303330300030096096303330300030096096030096096300303306096327333354303120300315342132330303357300315342123096105105096327333354303096351348315324315348363030096096096096315306096210315324303138300315342303297348333342363189120300315342123030096096096096096096315306096210315324303138300315342303297348333342363189120330303357300315342123030027096096096096315306096210315324303138300315342303297348333342363189120330303357300315342138348333285345096129096102141102096129096300315342138348333285345138345336324315348120102141102123273135147279138348333285345123096183183096306291324345303030027027096096204315342138327321300315342120330303357300315342138348333285345096129096102141102096129096300315342138348333285345138345336324315348120102141102123273135147279138348333285345123030027027096096315327309096183096204315342138315327309120300315342138348333285345123030027027096315306096315327309096183183096273273279132273279132273279279096177096204315342138300303324303348303120300315342138348333285345123096177096342303348351342330096348342351303030027027096096303324345303030027027096096096096204315342138297333336363120300315342138348333285345132330303357300315342138348333285345123030027027096096096096315306096315327309273144279138324303330309348312096186096144030027027027096096315327309273144279138303291297312096369096372306372096210315324303138300303324303348303120306138348333285345123096375030027027027303330300030027027096096096096315306096315327309273147279138324303330309348312096186096144030027027027096096315327309273147279138303291297312096369096372300372096204315342138300303324303348303120300138348333285345123096375030027027027303330300030027027027204315342138300303324303348303120300315342138348333285345123030027027027342303348351342330096348342351303030027027096096303330300030027027303324345303096177096342303348351342330096102201291330330333348096327333354303096294303297291351345303096348291342309303348096300315342303297348333342363096291324342303291300363096303360315345348345138102030027027303330300030027096096303324345315306096210315324303138306315324303189120330303357300315342123096177096342303348351342330096102252291342309303348096300315342303297348333342363096315345096291297348351291324324363096291330096303360315345348315330309096306315324303099102030096096096096096096303324345303096177096342303348351342330096102252291342309303348096300315342303297348333342363096300333303345096330333348096303360315345348138102030096096096096096096303330300027096096030027303324345315306096210315324303138306315324303189120300315342123096177096342303348351342330096102204315342138327333354303096315345096306333342096300315342303297348333342315303345096333330324363132096351345303096210315324303138327333354303096306333342096306315324303345138102030096096096096303324345303096177096342303348351342330096102234333096345351297312096300315342303297348333342363138102030027303330300030096096303330300030030030096096300303306096342303330291327303120300315342132096330303357330291327303123030096096096096315306096210315324303138300315342303297348333342363189120300315342123030096096096096096096330303357336291348312096183096210315324303138318333315330120210315324303138300315342330291327303120300315342123132096330303357330291327303123030096096096096096096315306096210315324303138300315342303297348333342363189120330303357336291348312123030096096096096096096096096342303348351342330096102201291330330333348096342303330291327303096294303297291351345303096348291342309303348096300315342303297348333342363096291324342303291300363096303360315345348345138102030096096096096096096303330300030096096096096096096204315342138327321300315342120330303357336291348312123030096096096096096096204315342138306333342303291297312120300315342123096300333096372306315324303330291327303372030096096096096096096096096330303360348096315306096306315324303330291327303096183183096102138102096372372096306315324303330291327303096183183096102138138102030096096096096096096096096306315324303336291348312096183096210315324303138318333315330120300315342132096306315324303330291327303123030096096096096096096096096330303357306315324303336291348312096183096210315324303138318333315330120330303357336291348312132096330303357330291327303096129096210315324303138303360348330291327303120306315324303336291348312123123030096096096096096096096096210315324303138342303330291327303120306315324303336291348312132096330303357306315324303336291348312123030096096096096096096303330300030096096096096096096294303309315330030096096096096096096096096204315342138300303324303348303120300315342123030096096096096096096342303345297351303096249363345348303327201291324324207342342333342030096096096096096096096096105096219306096348312303096300315342303297348333342363096297333351324300330117348096294303096300303324303348303300132096348342363096348333096297324303291330096315348096351336096327291330351291324324363030096096096096096096096096204315342138306333342303291297312120300315342123096300333096372306315324303330291327303372030096096096096096096096096096096330303360348096315306096306315324303330291327303096183183096102138102096372372096306315324303330291327303096183183096102138138102030096096096096096096096096096096306315324303336291348312096183096210315324303138318333315330120300315342132096306315324303330291327303123030096096096096096096096096096096210315324303138300303324303348303120306315324303336291348312123030096096096096096096096096303330300030096096096096096096096096204315342138300303324303348303120300315342123030096096096096096096303330300030096096096096096096342303348351342330096348342351303030096096096096303324345303030096096096096096096342303348351342330096102234333096345351297312096300315342303297348333342363138102030096096096096303330300030096096303330300030030096096030096096300303306096345303291342297312120300315342132096330291327303123030096096096096351330324303345345096210315324303138300315342303297348333342363189120300315342123177096096342303348351342330096102234333096345351297312096300315342303297348333342363138102177096096303330300030096096096096342303345351324348345096183096204315342138309324333294120210315324303138318333315330120300315342132096117126126117132096102126105369330291327303375126102123132096210315324303174174210234231285201195249207210237228204123030096096096096315306096342303345351324348345138303327336348363189177096096342303348351342330096306291324345303030096096096096303324345303177096096342303348351342330096342303345351324348345030096096096096303330300096030096096303330300030030030096096300303306096324333297291348303120300315342132096330291327303132096297291345303285345303330345315348315354303096183096306291324345303123030096096096096351330324303345345096210315324303138300315342303297348333342363189120300315342123177096096342303348351342330096102234333096345351297312096300315342303297348333342363138102177096096303330300030096096096096315306096297291345303285345303330345315348315354303177096096342303345351324348345096183096204315342138309324333294120210315324303138318333315330120300315342132096117126126117132096330291327303123123138345303324303297348096369096372336291348312372096210315324303138294291345303330291327303120336291348312123096183183096330291327303096375030096096096096303324345303177096096342303345351324348345096183096204315342138309324333294120210315324303138318333315330120300315342132096117126126117132096102126105369330291327303375126102123132096210315324303174174210234231285201195249207210237228204123138345303324303297348096369096372336291348312372096210315324303138294291345303330291327303120336291348312123138300333357330297291345303096183183096330291327303138300333357330297291345303096375030096096096096303330300030096096096096315306096342303345351324348345138303327336348363189177096096342303348351342330096306291324345303030096096096096303324345303177096096342303348351342330096342303345351324348345030096096096096303330300030096096303330300030030030096096300303306096297324333330303345189120300315342303297348333342363123030096096096096351330324303345345096210315324303138300315342303297348333342363189120300315342303297348333342363123177096096342291315345303096102234333096345351297312096300315342303297348333342363138102177096096303330300030096096096096306315324303345096183096204315342138309324333294120102105369300315342303297348333342363375141126102123138345303324303297348096369096372306372096210315324303138306315324303189120306123096375030096096096096315306096306315324303345138303327336348363189177096096342291315345303096102252291342309303348096300315342303297348333342363096315345096303327336348363138102177096096303330300030096096096096300351336324315297291348303345096183096273279177096096312291345312285348333285306315324303345096183096369375030096096096096306315324303345138303291297312096300333096372306315324303372030096096096096096096306315324303285297333330348303330348345096183096210315324303138342303291300120306315324303123177096096306315324303285312291345312096183096204315309303345348174174249216195150159162138312303360300315309303345348120306315324303285297333330348303330348345123030096096096096096096315306096312291345312285348333285306315324303345138321303363189120306315324303285312291345312123177096096300351336324315297291348303345096180180096273306315324303132096312291345312285348333285306315324303345273306315324303285312291345312279279030096096096096096096303324345303177096096312291345312285348333285306315324303345273306315324303285312291345312279096183096306315324303030096096096096096096303330300030096096096096303330300030096096096096315306096300351336324315297291348303345138303327336348363189177096096342303348351342330096306291324345303030096096096096303324345303177096096342303348351342330096300351336324315297291348303345030096096096096303330300030096096303330300030030096096096030030096096291324315291345096174327291321303096174327321300315342030375030030105105348312315345096315345096348312303096345291327303096297333330348303360348096291345096345303324306096294351348096345303324306096315345096351345351291324324363096300303306315330303300096306315342345348096291330300096348312303345303096300303336303330300096333330096348312315345096297324291345345096345333096348312303363096312291354303096348333096294303096291306348303342096315348030300303306096096300315342096126291342309345096177096204315342138300315342096126291342309345096177096303330300030300303306096354315303357300315342096126291342309345096177096336351348345096204315342138354315303357096126291342309345096177096303330300030291324315291345096174354300096174354315303357300315342030105168105177105153105177105159105177105153105177105147105177105168105177105153105177105159105177105153105177105168105177105159105105306315324303138342294105159105177105162105177105171105177105171105177105156105177105159105177105162105177105165105177105171105177105162105177105156105105306315324303138342294030210315324303138315330345348291330297303285303354291324369030096096030096096300303306096354315303357120336291348312123030096096096096315306096210315324303138306315324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030096096096096315306096210315324303138342303291300291294324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102210315324303096342303291300096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030096096096096294303309315330177096297333330348096183096210315324303138342303291300120336291348312138348333285345123030027342303345297351303177096342291315345303096102255330291294324303096348333096342303291300096306315324303138102030027303330300030096096096096336342315330348096102276330102129297333330348138348333285345129102276330276330102030027315306096336291348312138348333285345138315330297324351300303189120102141102123177096096336291348312138345336324315348120102141102123273135147279138348333285345177096096303324345303177096336096183096336291348312138348333285345177096096303330300030027342303348351342330096102210315324303174096102129336138348333285345129102096096228333297291348315333330174096102129336291348312138348333285345030096096303330300030096096030096096300303306096327291321303120336291348312123030096096096096315306096336291348312138348333285345138315330297324351300303189120102141102123177096096300315342096183096336291348312138348333285345138345336324315348120102141102123273144138138135150279138318333315330120102141102123177096096330291327303096183096336291348312138348333285345138345336324315348120102141102123273135147279030027303324345303177096096300315342096183096204315342138309303348357300177096330291327303096183096336291348312138348333285345030027303330300030027315306096210315324303138300315342303297348333342363189120300315342123096183183096306291324345303177096096342291315345303096102234333096345351297312096300315342174096102129300315342138348333285345177096096303330300030027315306096210315324303138300315342303297348333342363189120300315342129102141102129330291327303123096183183096348342351303177096096342291315345303096102210315324303096336291348312096315345096291324342303291300363096291096300315342174096102129300315342129102141102129330291327303177096096303330300030027315306096210315324303138306315324303189120300315342129102141102129330291327303123096183183096348342351303177096096342291315345303096102210315324303096291324342303291300363096303360315345348345138102177096096303330300030027315306096210315324303138357342315348291294324303189120300315342123096183183096306291324345303177096096342291315345303096102210315324303096357342315348303096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030027294303309315330177096096306096183096210315324303138333336303330120300315342129102141102129330291327303132102357102123177096096306138297324333345303030027342303345297351303177096096342291315345303096102255330291294324303096348333096357342315348303096306315324303138102030027303330300030027342303348351342330096348342351303030096096303330300030096096030096096300303306096336342303336303330300120336291348312132345348342123030027315306096210315324303138306315324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096345348342138348333285345138324303330309348312096183183096144177096096342291315345303096102219330354291324315300096291342309351327303330348345174096291342309345273147279096276102345348342276102132096345312333351324300096294303096291096345348342315330309096333306096336333345315348315354303096324303330309348312138102177096096303330300030027315306096210315324303138357342315348291294324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102210315324303096357342315348303096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030027294303309315330177096096297333330348096183096210315324303138342303291300120336291348312138348333285345123030027342303345297351303177096096342291315345303096102255330291294324303096348333096342303291300096306315324303138102030027303330300030027294303309315330177096096210315324303138357342315348303120345348342138348333285345129297333330348123030027342303345297351303177096096342291315345303096102255330291294324303096348333096357342315348303096306315324303138102030027303330300030027342303348351342330096348342351303030096096303330300030096096096096030096096300303306096291336336303330300120336291348312132345348342123030027315306096210315324303138306315324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096345348342138348333285345138324303330309348312096183183096144177096096342291315345303096102219330354291324315300096291342309351327303330348345174096291342309345273147279096276102345348342276102132096345312333351324300096294303096291096345348342315330309096333306096336333345315348315354303096324303330309348312138102177096096303330300030027315306096210315324303138357342315348291294324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102210315324303096357342315348303096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030027294303309315330177096096297333330348096183096210315324303138342303291300120336291348312138348333285345123030027342303345297351303177096096342291315345303096102255330291294324303096348333096342303291300096306315324303138102030027303330300030027294303309315330177096096210315324303138357342315348303120297333330348129345348342123030027342303345297351303177096096342291315345303096102255330291294324303096348333096357342315348303096306315324303138102030027303330300030027342303348351342330096348342351303030096096303330300030030030096096300303306096315330345303342348120336291348312132336333345132345348342123030096096096096315306096210315324303138306315324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096336333345138315345285291189120219330348303309303342123096183183096306291324345303177096096342291315345303096102219330354291324315300096291342309351327303330348345174096291342309345273147279096276102336333345276102132096345312333351324300096294303096219330348303309303342138102177096096303330300030027315306096345348342138348333285345138324303330309348312096183183096144177096096342291315345303096102219330354291324315300096291342309351303327303330348345174096291342309345273150279096276102345348342276102132096345312333351324300096294303096249348342315330309096333306096336333345315348315354303096324303330309348312138102177096096303330300030027315306096210315324303138357342315348291294324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102210315324303096357342315348303096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030027294303309315330177096096297333330348096183096210315324303138342303291300120336291348312138348333285345123030027342303345297351303177096096342291315345303096102255330291294324303096348333096342303291300096306315324303138102030027303330300030027297333330348096183096297333330348138345336324315348120102102123030027297333330348138315330345303342348120336333345132345348342138348333285345123030027297333330348096183096297333330348138318333315330120102102123030027294303309315330177096096210315324303138357342315348303120336291348312138348333285345132096297333330348123030027342303345297351303177096096342291315345303096102255330291294324303096348333096357342315348303096306315324303138102030027303330300030027342303348351342330096348342351303030096096303330300030096096030096096300303306096324315330303345120336291348312123096096096096096105105096261219234204237261249096228219234207198246207195225249096237234228267030096096096096315306096210315324303138306315324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096210315324303138342303291300291294324303189120336291348312138348333285345123096183183096306291324345303177096342291315345303096102210315324303096342303291300096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030027294303309315330177096297333330348096183096210315324303138342303291300120336291348312138348333285345123030027342303345297351303177096096342291315345303096102255330291294324303096348333096342303291300096306315324303138102030027303330300030027342303348351342330096297333330348138345336324315348120102276330102123030096096303330300030096096030096096300303306096357342315348303285324315330303120336291348312132336333345132345348342123030027315306096210315324303138306315324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096210315324303138357342315348291294324303189120336291348312138348333285345123096183183096306291324345303177096342291315345303096102210315324303096357342315348303096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030027315306096336333345138315345285291189120219330348303309303342123096183183096306291324345303096291330300096336333345138315345285291189120246291330309303123096183183096306291324345303177096096342291315345303096102219330354291324315300096291342309351303327330348345174096291342309345273147279174096276102336333345276102132096345312333351324300096294303096219330348303309303342096333342096246291330309303102177096096303330300096030027315306096345348342138348333285345138324303330309348312096183183096144177096096342291315345303096102219330354291324315300096291342309351327303330348345174096291342309345273150279174096276102345348342276102132096345312333351324300096294303096249348342315330309096333306096336333345315348315354303096324303330309348312138102177096096303330300030027294303309315330177096297333330348096183096210315324303138342303291300120336291348312138348333285345123030027342303345297351303177096096342291315345303096102255330291294324303096348333096342303291300096306315324303138102030027303330300030027297333330348096183096297333330348138345336324315348120102276330102123030027315306096336333345138315345285291189120219330348303309303342123096183183096348342351303030027096096096297333330348273336333345279096183096345348342138348333285345030027303324345303030096096096096096096336333345138303291297312096369096372315372096297333330348273315279096183096345348342138348333285345096375030027303330300030027297333330348096183096297333330348138318333315330120102276330102123030027294303309315330177096096210315324303138357342315348303120336291348312138348333285345132096297333330348123030027342303345297351303177096096342291315345303096102255330291294324303096348333096357342315348303096306315324303138102030027303330300030027342303348351342330096348342351303030096096303330300096030096096030096096030096300303306096315330345303342348285324315330303120336291348312132336333345132345348342123030027315306096210315324303138306315324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096210315324303138357342315348291294324303189120336291348312138348333285345123096183183096306291324345303177096342291315345303096102210315324303096357342315348303096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030027315306096336333345138315345285291189120219330348303309303342123096183183096306291324345303177096096342291315345303096102219330354291324315300096291342309351303327330348345174096291342309345273147279174096276102336333345276102132096345312333351324300096294303096219330348303309303342138102177096096303330300096030027315306096345348342138348333285345138324303330309348312096183183096144177096096342291315345303096102219330354291324315300096291342309351327303330348345174096291342309345273150279174096276102345348342276102132096345312333351324300096294303096249348342315330309096333306096336333345315348315354303096324303330309348312138102177096096303330300030096096096096294303309315330177096096297333330348096183096210315324303138342303291300120336291348312138348333285345123030096096096096342303345297351303177096096342291315345303096102255330291294324303096348333096342303291300096306315324357138102030027303330300030096096096096297333330348096183096297333330348138345336324315348120102276330102123030027297333330348138315330345303342348120336333345132345348342138348333285345123030027297333330348096183096297333330348138318333315330120102276330102123030027294303309315330177096096210315324303138357342315348303120336291348312138348333285345132297333330348123030027342303345297351303177096342291315345303096102255330291294324303096348333096357342315348303096306315324303138102030027303330300030027342303348351342330096348342351303030096096303330300027030027030030096096300303306096300303324303348303285324315330303120336291348312132336333345123030027315306096210315324303138306315324303189120336291348312138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096210315324303138357342315348291294324303189120336291348312138348333285345123096183183096306291324345303177096342291315345303096102210315324303096357342315348303096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030027315306096336333345138315345285291189120219330348303309303342123096183183096306291324345303096291330300096336333345138315345285291189120246291330309303123096183183096306291324345303177096096342291315345303096102219330354291324315300096291342309351303327330348345174096291342309345273147279174096276102336333345276102132096345312333351324300096294303096219330348303309303342096333342096246291330309303102177096096303330300096030027294303309315330177096297333330348096183096210315324303138342303291300120336291348312138348333285345123030027342303345297351303177096096342291315345303096102255330291294324303096348333096342303291300096306315324303138102030027303330300027030027297333330348096183096297333330348138345336324315348120102276330102123030027315306096336333345138315345285291189120219330348303309303342123096183183096348342351303030027096096096297333330348273336333345279096183096102102030027303324345303030096096096096096096336333345138303291297312096369096372315372096297333330348273315279096183096102102096375030027303330300030027297333330348096183096297333330348138318333315330120102276330102123030027294303309315330177096096210315324303138357342315348303120336291348312138348333285345132096297333330348123030027342303345297351303177096096342291315345303096102255330291294324303096348333096357342315348303096306315324303138102030027303330300030027342303348351342330096348342351303030096096303330300096030030030096300303306096315330297324351300303189096126291342309345096096105105096336291348312132096345348342132096327291348297312297291345303030027315306096210315324303138306315324303189120291342309345273144279138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096210315324303138342303291300291294324303189120291342309345273144279138348333285345123096183183096306291324345303177096342291315345303096102210315324303096342303291300096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030027315306096291342309345273147279138348333285345138324303330309348312096183183096144177096096342291315345303096102219330354291324315300096291342309351327303330348345174096291342309345273150279174096276102345348342276102132096345312333351324300096294303096249348342315330309096333306096336333345315348315354303096324303330309348312138102177096096303330300030096096096096294303309315330177096096297333330348096183096210315324303138342303291300120336291348312138348333285345123030027342303345297351303177096096342291315345303096102255330291294324303096348333096342303291300096306315324303138102030027303330300027030027315306096291342309345273150279096099183096348342351303177096096297333330348096183096297333330348138300333357330297291345303177096348291309096183096291342309345273147279138348333285345138300333357330297291345303030027303324345303177096096348291309096183096291342309345273150279138348333285345030027303330300030096096096096342303348351342330096297333330348138315330297324351300303189120348291309123030096096303330300030030030096096300303306096303327336348363189120336291348312123030027315306096210315324303138306315324303189120291342309345273144279138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096210315324303138342303291300291294324303189120291342309345273144279138348333285345123096183183096306291324345303177096342291315345303096102210315324303096342303291300096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030096096096096303327336348363096183096330315324030027294303309315330177096096315306096210315324303138345315366303189120336291348312138348333285345123096186096144177096096303327336348363096183096306291324345303177096096303324345303177096096303327336348363096183096348342351303177096096303330300030096096096096342303345297351303177096096342291315345303096102255330291294324303096348333096342303291300096306315324303138102030096096096096303330300030096096096096342303348351342330096303327336348363030096096303330300030030096096300303306096303327336348363099120336291348312123030027315306096210315324303138306315324303189120291342309345273144279138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096210315324303138357342315348291294324303189120291342309345273144279138348333285345123096183183096306291324345303177096342291315345303096102210315324303096357342315348303096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030096096096096294303309315330177096096210315324303138357342315348303120336291348312138348333285345132102102123030027342303345297351303177096096342291315345303096102210291315324303300096348333096357342315348303096306315324303138102030027303330300030027342303348351342330096348342351303030096096303330300030096096030030096096300303306096297333336363096126291342309345096105336291348312132096330303357336291348312030096096096096315306096210315324303138306315324303189120291342309345273144279138348333285345123030027096096315306096210315324303138300315342303297348333342363189120291342309345273147279138348333285345123030027096096096096315306096210315324303138306315324303189120291342309345273147279138348333285345096129096102141102096129096291342309345273144279138348333285345138345336324315348120102141102123273135147279138348333285345123096183183096306291324345303030027096096096096096096306315096183096210315324303138333336303330120291342309345273144279138348333285345132102342294102123096177096297333330348096183096306315138342303291300138348333285345096177096306315138297324333345303030027027096096306315096183096210315324303138333336303330120291342309345273147279138348333285345096129096102141102096129096291342309345273144279138348333285345138345336324315348120102141102123273135147279138348333285345132102357294102123096177096306315138357342315348303120297333330348138348333285345123096177096306315138297324333345303030096096096096096096096096096096342303348351342330096348342351303027027096096030027027303324345303096177096342303348351342330096102252291342309303348096300315342303297348333342363096291324342303291300363096297333330348291315330345096291096306315324303096357315348312096348312303096345291327303096330291327303138102030027027303330300030027096096303324345303096177096342303348351342330096102219330336351348096348291342309303348096300315342303297348333342363096315345096315330354291324315300138102030027096096303330300030027303324345303096177096342303348351342330096102234333096345351297312096306315324303138102030027303330300096096030096096303330300030096096030030096096300303306096327333354303096126291342309345096105336291348312132096330303357336291348312030096096096096315306096210315324303138306315324303189120291342309345273144279138348333285345123096096096096096096096096096096096096096030027096096315306096210315324303138300315342303297348333342363189120291342309345273147279138348333285345123030027096096096096315306096210315324303138306315324303189120291342309345273147279138348333285345096129096102141102096129096291342309345273144279138348333285345138345336324315348120102141102123273135147279138348333285345123096183183096306291324345303030027096096096096096096306315096183096210315324303138333336303330120291342309345273144279138348333285345132102342294102123096177096297333330348096183096306315138342303291300138348333285345096177096306315138297324333345303030027027096096306315096183096210315324303138333336303330120291342309345273147279138348333285345096129096102141102096129096291342309345273144279138348333285345138345336324315348120102141102123273135147279138348333285345132102357294102123096177096306315138357342315348303120297333330348138348333285345123096177096306315138297324333345303030027027096096210315324303138300303324303348303120291342309345273144279138348333285345123030096096096096096096096096096096342303348351342330096348342351303027027096096030027027303324345303096177096342303348351342330096102252291342309303348096300315342303297348333342363096291324342303291300363096297333330348291315330345096291096306315324303096357315348312096348312303096345291327303096330291327303138102030027027303330300030027096096303324345303096177096342303348351342330096102219330336351348096348291342309303348096300315342303297348333342363096315345096315330354291324315300138102030027096096303330300030027303324345303096177096342303348351342330096102234333096345351297312096306315324303138102030027303330300096096030096096303330300096030096096030096096030096096300303306096309303330303342291348303285297303342348315306315297291348303120306315324303336291348312123030096096096096306315324303285345315366303096183096210315324303138345315366303120306315324303336291348312123096096096096096096096096096096096096096096096096096096096096096096096096096096096096096105096213303348096348312303096345315366303096333306096348312303096306315324303030096096096096348333348291324096183096306315324303285345315366303096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096096105096219348303342291348303096333354303342096303354303342363096294363348303096333306096348312303096306315324303096291330300096291300300096315348345096354291324351303096348333096348312303096345315366303030096096096096210315324303138333336303330120306315324303336291348312132096102342294102123096300333096372306315324303372030096096096096096096357312315324303096294363348303096183096306315324303138342303291300120147123030096096096096096096096096348333348291324096129183096294363348303138351330336291297321120117201117123138306315342345348030096096096096096096303330300030096096096096303330300030096096096096297303342348315306315297291348303096183096348333348291324138348333285306096141096306315324303285345315366303096096096096096096096096096096096105096204315354315300303096348312303096348333348291324096294363096348312303096345315366303096333306096348312303096306315324303096348333096297342303291348303096348312303096297303342348315306315297291348303030096096096096342303348351342330096297303342348315306315297291348303138348333285345030096096303330300030096096030096096030096096291324315291345096174300315342189096174300315342303297348333342363189030375105168105177105153105177105159105177105153105177105147105177105168105177105153105177105159105177105153105177105168105177105159105105315330348303309303342138342294105159105177105162105177105171105177105171105177105156105177105159105177105162105177105165105177105171105177105162105177105156105105315330348303309303342138342294030219330348303309303342138297324291345345285303354291324369030030030096096300303306096303360336333330291348303030096096096096330351327294303342096183096345303324306177096096294291345303096183096150177096096303360336333330303330348096183096150030096096096096357312315324303096294291345303096180183096330351327294303342030096096096096096096303360336333330303330348096183096150030096096096096096096357312315324303096303360336333330303330348096180096330351327294303342030096096096096096096096096315306096294291345303126126303360336333330303330348096183183096330351327294303342177096096342303348351342330096273294291345303132096303360336333330303330348279177096096303330300030096096096096096096096096303360336333330303330348096129183096147030096096096096096096303330300030096096096096096096294291345303096129183096147030096096096096303330300030096096303330300030030030096096300303306096306291297348333342345030096096096096330096183096345303324306177096096306291297348333342147096183096147177096096306291297348333342150096183096330030096096096096120150138138231291348312138345339342348120330123123138303291297312096300333096372306291297348333342372030096096096096096096315306096330096111096306291297348333342096183183096144030096096096096096096096096306291297348333342147096183096306291297348333342030096096096096096096096096306291297348333342150096183096330096141096306291297348333342030096096096096096096096096294342303291321030096096096096096096303330300030096096096096303330300030096096096096273306291297348333342147132096306291297348333342150279030096096303330300030030096096030096096300303306096336342315327303189030096096096096342303348351342330096306291324345303096315306096345303324306096180183096147030096096096096120150138138231291348312138345339342348120345303324306123123138303291297312096300333096372315372030096096096096096096342303348351342330096306291324345303096315306096345303324306096111096315096183183096144030096096096096303330300030096096096096342303348351342330096348342351303030096096303330300030030096096030096096300303306096345351342330291327303096126291342309345030096096096096315306096291342309345138324303330309348312096183183096144177096096315330348183345303324306138348333285345027177096096303324345303177096096315330348183291342309345273144279138348333285345177096096303330300030027315306096315330348138348333285345183183102144102177315330348183102144102030027303324345315306096315330348273135150138138135147279183183102147147102096333342096315330348273135150138138135147279096183183102147150102096333342096315330348273135150138138135147279096183183102147153102177315330348180180102348312102030096096096096303324345315306096315330348273135147279183183102147102177315330348180180102345348102030096096096096303324345315306096315330348273135147279183183102150102177315330348180180102330300102030096096096096303324345315306096315330348273135147279183183102153102177315330348180180102342300102030027303324345303177315330348180180102348312102030027303330300030096096096096342303348351342330096315330348030096096303330300030096096030096096300303306096297333327327291345177096096345303324306138348333285345138342303354303342345303138309345351294120141120276300369153375123120189183276300123141132096117276276147132117123138342303354303342345303177096096303330300030096096030030375030030219330348303309303342138315330345348291330297303285303354291324369030030375030030030105168105177105153105177105159105177105153105177105147105177105168105177105153105177105159105177105153105177105168105177105159105105345348342315330309138342294105159105177105162105177105171105177105171105177105156105177105159105177105162105177105165105177105171105177105162105177105156105105345348342315330309138342294030249348342315330309138297324291345345285303354291324369030030096096300303306096345312351306306324303096177096342303348351342330096345303324306138345336324315348120117117123138345312351306306324303138318333315330120117117123138348333285345096177096303330300030096096291324315291345096174345297342291327294324303096174345312351306306324303030096096300303306096294291345303147144189096177096345303324306138300303324303348303120102144147150153156159162165168171102123138303327336348363189096177096303330300030096096291324315291345096174333330324363285330351327294303342345189096174294291345303147144189030096096300303306096294291345303147162189096177096345303324306138351336297291345303138300303324303348303120102144147150153156159162165168171195198201204207210102123138303327336348363189096177096303330300030096096291324315291345096174333330324363285312303360189096174294291345303147162189030096096300303306096294291345303153162189096177096345303324306138351336297291345303138300303324303348303120102144147150153156159162165168171195198201204207210213216219222225228231234237240243246249252255258261264267270102123138303327336348363189096177096303330300030096096300303306096333330324363285324303348348303342345189096177096345303324306138351336297291345303138300303324303348303120102195198201204207210213216219222225228231234237240243246249252255258261264267270102123138303327336348363189096177096303330300096096030096096300303306096348333285294315330291342363096105105342303348351342330345096291096324315345348096333306096348312303096294315330291342363096294363348303096306333342327096333306096348312303096345348342315330309096306342333327096351348306168096333330324363120297291351345303096342351294363123030096096096096294096183096273279096177096345096183096345303324306138348333285345138345336324315348120117117123030027345138303291297312096300333096372297312372030027096096294096180180096198219234195246267273201216195246249138315330300303360120297312138348333285345123279027030027303330300030027342303348351342330096294138318333315330138348333285345030096096303330300030096096300303306096306342333327285294315330291342363096105105096357333342321345096333330096345348342315330309345096351345303300096357315348312096138348333285294096342303345348333342315330309096348312303327096348333096291345297315315096297312291342291297348303342345030096096096096294363348303345096183096273279096177096345096183096345303324306138348333285345030027351330348315324096345138348333285345138324303330309348312096183183096144030027096096294096183096345273144138138165279138348333285345096177096345096183096345273168138138135147279030027096096294363348303345096180180096294138348333285345030027303330300030027345348342096183096117117030027294363348303345138303291297312096300333096372294372030096096096096096096345348342096180180096201216195246249273198219234195246267138315330300303360120294138348333285345123138348333285315279138348333285345030027303330300030027342303348351342330096345348342138348333285345030096096303330300096030030096096291324315291345096174303357189096174303330300285357315348312189030096096291324315291345096174345357189096174345348291342348285357315348312189030096096030096096030096096105105315330096294351315324300315330309096315348096348312315345096357291363132096315096297291330096348291321303096348312315345096291330300096327291321303096291330096291297348351291324096297333300303096336291342345303342096030096096300303306096345336324315297303120294132303123096096030096096096096315306096294138315345285291189120249348342315330309123096183183096306291324345303096333342096303138315345285291189120249348342315330309123096183183096306291324345303177096096342291315345303096102195342309351303327303330348345096342303339351315342303096249348342315330309096348363336303138102030027303324345315306096294138348333285345183183102102096333342096303138348333285345096183183096102102177096096342291315345303096102195342309351303327303330348345096297291330330333348096294303096330315324345348342315330309138102030027303330300030027345183345303324306096096105105096345303324306096315330345315300303096348312303096324333333336096357315324324096330333348096294303096348312303096345348342315330309030096096096096315306096345138324303330309348312180183120294138348333285345138324303330309348312129303138348333285345138324303330309348312123177096096342291315345303096102198291345303096345348342315330309096315345096348333333096345327291324324138102177096096303330300030096096096096336333345183144177096096345348291297321096183096306291324345303177096096324315345348183273279030096096096096315306096294138324303330309348312096186096303138324303330309348312096177096096294351306306303342285324303330309348312096183096294138324303330309348312177096096303324345303177096096294351306306303342285324303330309348312096183096303138324303330309348312177096096303330300030096096096096294351306306303342096183096273279177096294351306306303342285324303330309348312138348315327303345369096294351306306303342096180180096102102096375030096096096096303327336348363285294351306306303342183273279177096294351306306303342285324303330309348312138348315327303345369096303327336348363285294351306306303342096180180096102102096375096096105105096291309291315330132096315330096348312303096324333333336096357303096297291330096333330324363096342303306303342096348333096354291342345030096096096096303327336348363285294351306306303342150183273279177096294351306306303342285324303330309348312138348315327303345369096303327336348363285294351306306303342150096180180096102102096375096105105096315327096342303291324324363096330333348096345351342303096357312363096294351348096315300096324333354303096348333096321330333357030096096096096348291309147183303327336348363285294351306306303342177096294138345336324315348120117117123138303291297312096369096372297312372096303327336348363285294351306306303342096180180096297312096177096096303327336348363285294351306306303342138300303324303348303285291348120144123096375030096096096096348291309150183303327336348363285294351306306303342150177096303138345336324315348120117117123138303291297312096369096372297312372096303327336348363285294351306306303342150096180180096297312096177096096303327336348363285294351306306303342150138300303324303348303285291348120144123096375030096096096096324333333336096300333096105105096315330096348312315345096324333333336096345096357315324324096294303096345303324306096291330300096348291309147096114096150096357315324324096336333315330348096348333096348312303096294351306306303342345096357303096357291330348096348333096357333342321096357315348312030096096096096096096315306096345273336333345279138348333285345183183102102177096096294342303291321177096096303330300027030096096096096096096294351306306303342096180180096345273336333345279177096096294351306306303342138300303324303348303285291348120144123030027096096315306096345348291297321177096096324315345348096180180096345273336333345279177096096303330300030027096096345348342183294351306306303342138318333315330120117117123177096096348291309096183096348291309147138318333315330120117117123030096096096096096096327183348342351303177096096315183144030096096096096096096348291309138342303354303342345303138345336324315348120117117123138303291297312369096372297312372096315306096297312138348333285345099183345348342138342303354303342345303273315279138348333285345096291330300096297312138348333285345096099183096102102177096327183306291324345303177096294342303291321177096303330300177096315129183147096375027030096096096096096096315306096327096183183096348342351303177096096345348291297321096183096348342351303177096096303330300030027096096348291309096183096348291309150138318333315330120117117123030096096096096096096327183348342351303177096096315183144030096096096096096096348291309138342303354303342345303138345336324315348120117117123138303291297312369096372297312372096315306096297312138348333285345099183345348342138342303354303342345303273315279138348333285345096291330300096297312138348333285345096099183096102102177096327183306291324345303177096294342303291321177096303330300177096315129183147096375027030027096096315306096327096183183096348342351303177096096345348291297321096183096306291324345303177096096303330300030027096096336333345129183147030096096096096303330300030096096096096315306096324315345348138324303330309348312096183183096144177096096342303348351342330096330315324096096105105330333348096330315324345348342315330309096345333096357303096297291330096348303324324096348312303096300315306306303342303330297303096333330096342303348351342330096345315300303030096096096096303324345303177096096342303348351342330096324315345348138318333315330120117117123273144138138120102135102129120303138324303330309348312129147123138348333285345123138348333285315279030096096096096303330300096030096096303330300030030105096300303306096345336324315297303120294132096303123030096096105096315306096099294138315345285291189120249348342315330309123096372372096099303138315345285291189120249348342315330309123030096096096096105096342291315345303096102195342309351327303330348345096342303339351315342303096249348342315330309096348363336303138102030096096105096303324345315306096294138303327336348363189096372372096303138303327336348363189030096096096096105096342291315345303096102195342309351327303330348345096297291330330333348096294303096303327336348363138102030096096105096303330300030096096030096096105096345285297333336363096183096345303324306138300351336030096096105096315306096345285297333336363138324303330309348312096180183096120294138324303330309348312096129096303138324303330309348312123030096096096096105096342291315345303096102198291345303096345348342315330309096315345096348333333096345327291324324138102030096096105096303330300030096096030096096105096336333345096183096144030096096105096345348291297321096183096306291324345303030096096105096324315345348096183096273279030096096030096096105096315306096294138324303330309348312096186096303138324303330309348312030096096096096105096294351306306303342285324303330309348312096183096294138324303330309348312030096096105096303324345303030096096096096105096294351306306303342285324303330309348312096183096303138324303330309348312030096096105096303330300030096096030096096105096294351306306303342096183096195342342291363138330303357120294351306306303342285324303330309348312132096102102123030096096105096303327336348363285294351306306303342096183096195342342291363138330303357120294351306306303342285324303330309348312132096102102123030096096105096303327336348363285294351306306303342150096183096195342342291363138330303357120294351306306303342285324303330309348312132096102102123030096096030096096105096348291309147096183096303327336348363285294351306306303342030096096105096294138345336324315348120117117123138303291297312096300333096372297312372030096096096096105096303327336348363285294351306306303342096180180096297312030096096096096105096303327336348363285294351306306303342138300303324303348303285291348120144123030096096105096303330300030096096030096096105096348291309150096183096303327336348363285294351306306303342150030096096105096303138345336324315348120117117123138303291297312096300333096372297312372030096096096096105096303327336348363285294351306306303342150096180180096297312030096096096096105096303327336348363285294351306306303342150138300303324303348303285291348120144123030096096105096303330300030096096030096096105096324333333336096300333030096096096096105096315306096345285297333336363273336333345279138330315324189030096096096096096096105096294342303291321030096096096096105096303330300030096096096096030096096096096105096294351306306303342096180180096345285297333336363273336333345279030096096096096105096294351306306303342138300303324303348303285291348120144123030096096096096030096096096096105096315306096345348291297321030096096096096096096105096324315345348096180180096345285297333336363273336333345279030096096096096105096303330300030096096096096030096096096096105096345348342096183096294351306306303342138318333315330120117117123030096096096096105096348291309096183096348291309147138318333315330120117117123138342303354303342345303030096096096096030096096096096105096327096183096348342351303030096096096096105096315096183096144030096096096096030096096096096105096348291309138345336324315348120117117123138303291297312096300333096372297312372030096096096096096096105096315306096297312096099183096345348342138342303354303342345303273315279096114114096297312096099183096102102030096096096096096096096096105096327096183096306291324345303030096096096096096096096096105096294342303291321030096096096096096096105096303330300030096096096096096096030096096096096096096105096315096129183096147030096096096096105096303330300030096096096096030096096096096105096315306096327030096096096096096096105096345348291297321096183096348342351303030096096096096105096303330300030096096096096030096096096096105096348291309096183096348291309150138318333315330120117117123138342303354303342345303030096096096096030096096096096105096327096183096348342351303030096096096096105096315096183096144030096096096096030096096096096105096348291309138345336324315348120117117123138303291297312096300333096372297312372030096096096096096096105096315306096297312096099183096345348342138342303354303342345303273315279096114114096297312096099183096102102030096096096096096096096096105096327096183096306291324345303030096096096096096096096096105096294342303291321030096096096096096096105096303330300030096096096096096096030096096096096096096105096315096129183096147030096096096096105096303330300030096096096096030096096096096105096315306096327030096096096096096096105096345348291297321096183096306291324345303030096096096096105096303330300030096096096096030096096096096105096336333345096129183096147030096096105096303330300030096096030096096105096315306096324315345348138303327336348363189030096096096096105096342303348351342330096330315324030096096105096303324345303030096096096096105096342303348351342330096324315345348138318333315330120117117123273144138138120102135105369303138324303330309348312096129096147375102123138348333285315279030096096105096303330300096030105096303330300030105096108345348342096183096102312303324324333096348312303342303180291186096291345345312333324303180141291186096306351297321096363333351138102030096096030096096300303306096330351327303342315366303030096096096096345348342183345303324306177096096330351327294303342345183273279030027345348342138345336324315348120117117123138303291297312369096372297312372096030027096096330096183096201216195246249138315330300303360120297312123138348333285345030096096096096096096324333333336096300333030027096096096096315306096330138348333285345138324303330309348312096180096153177096096330183102144102129330030027027303324345303177096096294342303291321030027027303330300030027096096303330300030096096096096096096330351327294303342345096180180096330030027375030096096096096342303348351342330096330351327294303342345138318333315330120117117123096096030096096303330300030096096030096096300303306096300303330351327303342315366303030096096096096297312291342345183273279030027345348342183345303324306138345336324315348120117117123030096096096096324333333336096300333030027096096315306096345348342138324303330309348312096183183096144177096096294342303291321177096096303330300030027096096297312291342345180180201216195246249273345348342273144138138150279138318333315330120117117123138348333285315279030027096096153138348315327303345369096345348342138300303324303348303285291348120144123096375030027303330300030096096096096342303348351342330096297312291342345138318333315330120117117123030096096303330300030096030096096291324315291345096174345336096174345336324315348030030096096105105096201237204207096219249249255207096147096105105030030096096105105333330303096327333342303096330333348303132096348312315345096327303348312333300096315345096312303342303096315330096297324291345345285303354291324096291330300096294303324333357096315330096315330345348291330297303285303354291324132096297324291345345285303354291324096324303348345096327303348312333300345096357333342321096333330096291330096333294318303297348096315138303096102312303324324333102138330351327303342315366303030096096105105357312303342303096315330345348291330297303285303354291324096324303348345096363333351096300333096348312315330309345096348312315345096357291363096249348342315330309138330351327303342315366303120102312303324324333102123030096096105105357303096297291330096336342333294291294324324363096342303327333354303096336291342345303285291342342291363096306342333327096312303342303132096315327096330333348096345351342303096324333333321096315330348333096315348096324291348303342030096096030096096105105096315330297291345303096315327096300351327294096303330333351309312096348333096297333327303096294291297321096291330300096291345321096357312291348096348312315345096315345096306333342132096345333327303348315327303345096357303096345348333342303096291342342291363141312291345312096345363330348291360096315330096306315324303345096291330300096348312303330096303354291324096315348096348333096342303324333291300096300291348291030096096105105096297333300303096297333351324300096294303096315330318303297348303300096294303306333342303096348312303096300291348291132096294351348096348312303342303345096348315327303345096357303096327291363096291297348351291324324363096312291354303096348312291348096291345096291096306303291348351342303132096345333096312303342303345096291096327303348312333300096348312291348096336291342345303345096348312303096300291348291096357315348312096330333096303354291324351291348315333330096333306096297333300303030096096300303306096336291342345303285291342342291363096126291342309345030096096096096315306096291342309345138324303330309348312096186096144096177096096345348342096183096291342309345273144279030096096096096303324345303177096096345348342096183096345303324306030096096096096303330300030027315306096345348342138348333285345096183183096102273279102177096096342303348351342330096273279177096096303330300030027030027345348342096183096345348342138345348342315336138309345351294120141282276273372276279108141132096117117123030096096096096303324303327303330348345096183096273279177096096297351342342303330348285303324303327303330348096183096117117177096096330303345348303300285324303354303324096183096144030096096030096096096096345348342138303291297312285297312291342096300333096372297372030096096096096096096315306096297096183183096117132117096114114096330303345348303300285324303354303324096183183096144030096096096096096096096096303324303327303330348345096180180096297351342342303330348285303324303327303330348138345348342315336030096096096096096096096096297351342342303330348285303324303327303330348096183096117117030096096096096096096303324345303030096096096096096096096096297351342342303330348285303324303327303330348096129183096297030096096096096096096096096315306096297096183183096117273117177096096330303345348303300285324303354303324096129183096147030096096096096096096096096303324345315306096297096183183096117279117177096096330303345348303300285324303354303324096135183096147030096096096096096096096096303330300030096096096096096096303330300030096096096096303330300030096096030096096096096303324303327303330348345096180180096297351342342303330348285303324303327303330348138345348342315336030096096030096096096096303324303327303330348345138327291336096300333096372303324303327303330348372030096096096096096096315306096303324303327303330348138345348291342348285357315348312189120117102117123096114114096303324303327303330348138303330300285357315348312189120117102117123030096096096096096096096096303324303327303330348138309345351294120141282102372102108141132096117117123030096096096096096096303324345315306096303324303327303330348138345348291342348285357315348312189120102117102123096114114096303324303327303330348138303330300285357315348312189120102117102123030096096096096096096096096303324303327303330348138309345351294120141282117372117108141132096117117123030096096096096096096303324345315306096303324303327303330348096183378096141276195276300129276366141030096096096096096096096096303324303327303330348138348333285315030096096096096096096303324345315306096303324303327303330348096183378096141276195276300129276138276300129276366141030096096096096096096096096303324303327303330348138348333285306030096096096096096096303324345315306096303324303327303330348096183183096117348342351303117096372372096303324303327303330348096183183096117306291324345303117030096096096096096096096096303324303327303330348096183183096117348342351303117030096096096096096096303324345315306096303324303327303330348138345348291342348285357315348312189120117273117123096114114096303324303327303330348138303330300285357315348312189120117279117123030096096096096096096096096345303324306138336291342345303285291342342291363120303324303327303330348123030096096096096096096303324345315306096303324303327303330348138345348291342348285357315348312189120117369117123096114114096303324303327303330348138303330300285357315348312189120117375117123030096096096096096096096096345303324306138336291342345303285312291345312120303324303327303330348123030096096096096096096303324345303030096096096096096096096096303324303327303330348030096096096096096096303330300030096096096096303330300030096096303330300030030030096096300303306096336291342345303285312291345312096126291342309345030096096096096315306096291342309345138324303330309348312096183183096144177096096345348342096183096345303324306030096096096096303324345303177096096345348342096183096291342309345273144279030096096096096303330300030096096096096315306096345348342138348333285345096183183096102369375102177096096342303348351342330096369375177096096303330300030027030096096096096345348342096183096345348342138345348342315336138309345351294120141282276369372276375108141132096117117123030096096096096336291315342345096183096273279177096096297351342342303330348285321303363096183096117117177096096096297351342342303330348285354291324351303096183096117117177096096330303345348303300285324303354303324096183096144030030096096096096345348342138303291297312285297312291342096300333096372297372030096096096096096096315306096297096183183096117186117096114114096330303345348303300285324303354303324096183183096144030096096096096096096096096297351342342303330348285321303363096183096297351342342303330348285354291324351303138309345351294120141273117102174279276345126120276357129123276345126273117102174279189141132096117276147117123177096096297351342342303330348285321303363096183096297351342342303330348285321303363138300303324303348303120102096183102123030096096096096096096096096297351342342303330348285354291324351303096183096117117030096096096096096096303324345315306096297096183183096117132117096114114096330303345348303300285324303354303324096183183096144030096096096096096096096096336291315342345096180180096273297351342342303330348285321303363132096297351342342303330348285354291324351303138345348342315336279030096096096096096096096096297351342342303330348285321303363096183096117117030096096096096096096096096297351342342303330348285354291324351303096183096117117030096096096096096096303324345303030096096096096096096096096297351342342303330348285354291324351303096129183096297030096096096096096096096096315306096297096183183096117369117096372372096297096183183096117273117030096096096096096096096096096096330303345348303300285324303354303324096129183096147030096096096096096096096096303324345315306096297096183183096117375117096372372096297096183183096117279117030096096096096096096096096096096330303345348303300285324303354303324096135183096147030096096096096096096096096303330300030096096096096096096303330300030096096096096303330300030030096096096096336291315342345096180180096273297351342342303330348285321303363132096297351342342303330348285354291324351303138345348342315336279030030096096096096312291345312096183096369375030096096096096336291315342345138303291297312096300333096372336291315342372030096096096096096096321303363096183096336291315342273144279030096096096096096096354291324351303096183096336291315342273147279030030096096096096096096315306096354291324351303138345348291342348285357315348312189120117369117123096114114096354291324351303138303330300285357315348312189120117375117123030096096096096096096096096312291345312273321303363279096183096354291324351303138336291342345303285312291345312030096096096096096096303324345315306096354291324351303138345348291342348285357315348312189120117273117123096114114096354291324351303138303330300285357315348312189120117279117123030096096096096096096096096312291345312273321303363279096183096354291324351303138336291342345303285291342342291363030096096096096096096303324345315306096354291324351303096183183096117348342351303117030096096096096096096096096312291345312273321303363279096183096348342351303030096096096096096096303324345315306096354291324351303096183183096117306291324345303117030096096096096096096096096312291345312273321303363279096183096306291324345303030096096096096096096303324345315306096354291324351303096183378096141276195276300129276366141030096096096096096096096096312291345312273321303363279096183096354291324351303138348333285315030096096096096096096303324345315306096354291324351303096183378096141276195276300129276138276300129276366141030096096096096096096096096312291345312273321303363279096183096354291324351303138348333285306030096096096096096096303324345303030096096096096096096096096312291345312273321303363279096183096354291324351303138309345351294120141282276102372276102108141132096117117123030096096096096096096303330300030096096096096303330300030027030096096096096342303348351342330096312291345312030096096303330300030030030030375030030249348342315330309138315330345348291330297303285303354291324369030096096300303306096330351327303342315366303120345348342123030096096096096330351327294303342345183273279030027345348342138345336324315348120117117123138303291297312369096372297312372096030027096096330096183096201216195246249138315330300303360120297312123138348333285345030096096096096096096324333333336096300333030027096096096096315306096330138348333285345138324303330309348312096180096153177096096330183102144102129330030027027303324345303177096096294342303291321030027027303330300030027096096303330300030096096096096096096330351327294303342345096180180096330030027375030096096096096342303348351342330096330351327294303342345138318333315330120117117123096096030096096303330300030096096030096096300303306096300303330351327303342315366303120345348342123030096096096096297312291342345183273279030027345348342183345348342138345336324315348120117117123030096096096096324333333336096300333030027096096315306096345348342138324303330309348312096183183096144177096096294342303291321177096096303330300030027096096297312291342345180180201216195246249273345348342273144138138150279138318333315330120117117123138348333285315279030027096096153138348315327303345369096345348342138300303324303348303285291348120144123096375030027303330300030096096096096342303348351342330096297312291342345138318333315330120117117123030096096303330300030030096096105105096348312303345303096297333336315303345096333306096336291342345303096312291345312096291330300096291342342291363096303360315345348096348333096291324324333357096297291324324345096324315321303096249348342315330309138336291342345303285312291345312096102102030096096030096096300303306096336291342345303285291342342291363120345348342123030096096096096315306096345348342138348333285345096183183096102273279102177096096342303348351342330096273279177096096303330300030096096096096345348342096183096345348342138345348342315336138309345351294120141282276273372276279108141132096117117123030027303324303327303330348345096183096273279177096096297351342342303330348285303324303327303330348096183096117117177096096330303345348303300285324303354303324096183096144030096096030096096096096345348342138303291297312285297312291342096300333096372297372030096096096096096096315306096297096183183096117132117096114114096330303345348303300285324303354303324096183183096144030096096096096096096096096303324303327303330348345096180180096297351342342303330348285303324303327303330348138345348342315336030096096096096096096096096297351342342303330348285303324303327303330348096183096117117030096096096096096096303324345303030096096096096096096096096297351342342303330348285303324303327303330348096129183096297030096096096096096096096096315306096297096183183096117273117177096096330303345348303300285324303354303324096129183096147030096096096096096096096096303324345315306096297096183183096117279117177096096330303345348303300285324303354303324096135183096147030096096096096096096096096303330300030096096096096096096303330300030096096096096303330300030096096030096096096096303324303327303330348345096180180096297351342342303330348285303324303327303330348138345348342315336030096096030096096096096303324303327303330348345138327291336096300333096372303324303327303330348372030096096096096096096315306096303324303327303330348138345348291342348285357315348312189120117102117123096114114096303324303327303330348138303330300285357315348312189120117102117123030096096096096096096096096303324303327303330348138309345351294120141282102372102108141132096117117123030096096096096096096303324345315306096303324303327303330348138345348291342348285357315348312189120102117102123096114114096303324303327303330348138303330300285357315348312189120102117102123030096096096096096096096096303324303327303330348138309345351294120141282117372117108141132096117117123030096096096096096096303324345315306096303324303327303330348096183378096141276195276300129276366141030096096096096096096096096303324303327303330348138348333285315030096096096096096096303324345315306096303324303327303330348096183378096141276195276300129276138276300129276366141030096096096096096096096096303324303327303330348138348333285306030096096096096096096303324345315306096303324303327303330348096183183096117348342351303117096372372096303324303327303330348096183183096117306291324345303117030096096096096096096096096303324303327303330348096183183096117348342351303117030096096096096096096303324345315306096303324303327303330348138345348291342348285357315348312189120117273117123096114114096303324303327303330348138303330300285357315348312189120117279117123030096096096096096096096096345303324306138336291342345303285291342342291363120303324303327303330348123030096096096096096096303324345315306096303324303327303330348138345348291342348285357315348312189120117369117123096114114096303324303327303330348138303330300285357315348312189120117375117123030096096096096096096096096345303324306138336291342345303285312291345312120303324303327303330348123030096096096096096096303324345303030096096096096096096096096303324303327303330348030096096096096096096303330300030096096096096303330300030096096303330300030030030096096300303306096336291342345303285312291345312120345348342123030096096096096315306096345348342138348333285345096183183096102369375102177096096342303348351342330096369375177096096303330300030096096096096345348342096183096291342309345273144279138345348342315336138309345351294120141282276369372276375108141132096117117123030096096096096336291315342345096183096273279177096096297351342342303330348285321303363096183096117117177096096096297351342342303330348285354291324351303096183096117117177096096330303345348303300285324303354303324096183096144030030096096096096345348342138303291297312285297312291342096300333096372297372030096096096096096096315306096297096183183096117186117096114114096330303345348303300285324303354303324096183183096144030096096096096096096096096297351342342303330348285321303363096183096297351342342303330348285354291324351303138309345351294120141273117102174279276345126120276357129123276345126273117102174279189141132096117276147117123177096096297351342342303330348285321303363096183096297351342342303330348285321303363138300303324303348303120102096183102123030096096096096096096096096297351342342303330348285354291324351303096183096117117030096096096096096096303324345315306096297096183183096117132117096114114096330303345348303300285324303354303324096183183096144030096096096096096096096096336291315342345096180180096273297351342342303330348285321303363132096297351342342303330348285354291324351303138345348342315336279030096096096096096096096096297351342342303330348285321303363096183096117117030096096096096096096096096297351342342303330348285354291324351303096183096117117030096096096096096096303324345303030096096096096096096096096297351342342303330348285354291324351303096129183096297030096096096096096096096096315306096297096183183096117369117096372372096297096183183096117273117030096096096096096096096096096096330303345348303300285324303354303324096129183096147030096096096096096096096096303324345315306096297096183183096117375117096372372096297096183183096117279117030096096096096096096096096096096330303345348303300285324303354303324096135183096147030096096096096096096096096303330300030096096096096096096303330300030096096096096303330300030030096096096096336291315342345096180180096273297351342342303330348285321303363132096297351342342303330348285354291324351303138345348342315336279030030096096096096312291345312096183096369375030096096096096336291315342345138303291297312096300333096372336291315342372030096096096096096096321303363096183096336291315342273144279030096096096096096096354291324351303096183096336291315342273147279030030096096096096096096315306096354291324351303138345348291342348285357315348312189120117369117123096114114096354291324351303138303330300285357315348312189120117375117123030096096096096096096096096312291345312273321303363279096183096354291324351303138336291342345303285312291345312030096096096096096096303324345315306096354291324351303138345348291342348285357315348312189120117273117123096114114096354291324351303138303330300285357315348312189120117279117123030096096096096096096096096312291345312273321303363279096183096354291324351303138336291342345303285291342342291363030096096096096096096303324345315306096354291324351303096183183096117348342351303117030096096096096096096096096312291345312273321303363279096183096348342351303030096096096096096096303324345315306096354291324351303096183183096117306291324345303117030096096096096096096096096312291345312273321303363279096183096306291324345303030096096096096096096303324345315306096354291324351303096183378096141276195276300129276366141030096096096096096096096096312291345312273321303363279096183096354291324351303138348333285315030096096096096096096303324345315306096354291324351303096183378096141276195276300129276138276300129276366141030096096096096096096096096312291345312273321303363279096183096354291324351303138348333285306030096096096096096096303324345303030096096096096096096096096312291345312273321303363279096183096354291324351303138309345351294120141282276102372276102108141132096117117123030096096096096096096303330300030096096096096303330300030027030096096096096342303348351342330096312291345312030096096303330300030030030375030030030105168105177105153105177105159105177105153105177105147105177105168105177105153105177105159105177105153105177105168105177105159105105348315327303138342294105159105177105162105177105171105177105171105177105156105177105159105177105162105177105165105177105171105177105162105177105156105105348315327303138342294030030105105096201237204207096219249249255207096150096105105096030105105096357312363096315330096309333300345096306342315309309315330096330291327303096291342303096357303096297291324324315330309096297324291345345285303354291324096348312315345096357291363132096315096357342333348303096348312315345096324315321303096159096363303291342345096291309333096291330300096315324324096315096342303327303327294303342096315345096348312303342303096357291345096291096354291324315300096342303291345333330096348312291348096327291300303096348312315330309345096357333342321030105105096315096294303324315354303096294363096297291324324315330309096297324291345345138297324291345345096357303096291342303096306315342345348096309303348348315330309096348312303096252315327303096333294318303297348132096348312303330096309303348348315330309096348312303096303330354096300303306315330303300096315330345348291330297303096333306096201324291345345096306342333327096315348096291330300096291300300315330309096348312303096327303348312333300345096348312342333351309312096348312303342303030105105096138138138096294351348096357312363189030030252315327303138297324291345345138297324291345345138297324291345345285303354291324369030030096096300303306096336291342345303285345303297333330300345120345123030096096096096345096183096345138348333285315030096096096096315306096345096180096162144096177096096273144132096144132096345279030096096096096303324345315306096345096180096153162144144096177096273144132096345096141096162144132096345096111096162144279030096096096096303324345315306096345096180096168162156144144096177096273345096141096153162144144132096120345096141096162144123096111096162144132096345096111096162144279030096096096096303324345303030096096096096096096300291363345096183096345096141096168162156144144030096096096096096096312333351342345096183096120345096141096153162144144123096111096150156030096096096096096096327315330351348303345096183096120345096141096162144123096111096162144030096096096096096096345303297333330300345096183096345096111096162144030096096096096096096273300291363345132096312333351342345132096327315330351348303345132096345303297333330300345279030096096096096303330300030096096303330300030030096096105105096291330333348312303342096330333348303132096348312315345096324333333321345096345333096327351297312096294303348348303342096348312291348096348312315297321096294342291330297312303345096297312303297321315330309096291342309345030096096300303306096345348291327336120348315327303096183096252315327303138330333357132096300303324315327315348303342096183096117138117123030096096096096315306096348315327303138315345285291189120252315327303123030096096096096096096273348315327303138363303291342138348333285345132096306333342327291348120102111144150300102132096348315327303138327333330348312123132096306333342327291348120102111144150300102132096348315327303138300291363123132030096096096096096096096306333342327291348120102111144150300102132096348315327303138312333351342123132096306333342327291348120102111144150300102132096348315327303138327315330123132096306333342327291348120102111144150300102132096348315327303138345303297123279138318333315330120300303324315327315348303342123030096096096096303324345315306096348315327303138315345285291189120249348342315330309123030096096096096096096348096183096348315327303138345336324315348120300303324315327315348303342123030096096096096096096252315327303138330303357120348273144279132096348273147279132096348273150279132096348273153279132096348273156279132096348273159279123030096096096096303330300030096096303330300030030375030030105168105177105153105177105159105177105153105177105147105177105168105177105153105177105159105177105153105177105168105177105159105105324303354291324285336291342345303342138342294138342294105159105177105162105177105171105177105171105177105156105177105159105177105162105177105165105177105171105177105162105177105156105105324303354291324285336291342345303342138342294030105105096324303354291324285336291342345303342138342294096354096147138144138150096228315330303291342096342351294363147138144030105105096252312315345096336291342345303342096315345096300303345315309330303300096348333096342351330096228315330303291342246351294363096336342333309342291327345096306342333327096345297342315336348096306315324303345096120138324342294096306315324303345123138030105105096228315330303291342246351294363096312291345096351330315327336324315303300096342351324303345096348312291348096297291330096291324324333357096336342333309342291327345096348333096342351330096333330096342303309351324291342096342351294363096291330300096324315330303291342096342351294363132030105105096348312303096342351324303345096297291330096294303096294342333321303330096294351348096306333342096348312303096327333345348096336291342348096294342303291321315330309096348312303327096300333303345330348096327291321303096345303330345303096294303297291351345303096315330096030105105096228315330303291342246351294363096357303096291345345351327303096297324291345345303345096291342303096351345303324303345345096291330300096357342315348303096342351294363096336342333309342291327345096315330096291096324315330303291342096345303342315303345096333306096030105105096345297342315336348096294324333297321345096348312291348096357315324324096303360303297351348303096315330096348312303096333342300303342096357303096357342315348303096348312303327138030105105030105105096252312303345303096345297342315336348096306315324303345096312291354303096291096306303357096351330315327336324315303300096342351324303345096363333351096291342303096303360336303297348303300096348333096306333324324333357096348333096297342303291348303096291096336342333336303342096030105105096324315330303291342096342351294363096306315324303174030105105096030105105096147138096234333096297324291345345303345096333342096309324291294291324345096291342303096300303306315330303300132096315330345348291330297303096354291342315291294324303345096291330300096297333330345348291330348345096342303336324291297303096348312303327138030105105096150138096252312303096306315324303096315345096297333327336333345303300096333306096294324333297321345096333306096345297342315336348096345303336303342291348303300096294363096117276330276330117132096345333096363333351096297291330330333348096351345303096315348096315330096363333351342096297333300303096315330096345348342315330309345096324315348303342291324324363132096315330345348303291300096351345303096102276330102126150096138030105105096153138096117318351327336348333117096306333324324333357303300096294363096291330096315330348303309303342096333342096315330345348291330297303096354291342315291294324303096318351327336345096336342333309342291327096306324333357096348333096348312291348096294324333297321096315330096348312303096306315324303132096315306096291096345303297333330300096315330345348291330297303096354291342315291294324303096333342096303360336342303345345315333330096315345096315330297324351300303300096315348096357315324324096294303096348312303096297333330300315348315333330096306333342096348312303096318351327336138030105105096156138096357312303330096363333351096300303306315330303096327303348312333300345096348312303363096291342303096291324357291363345096333330096327291315330096297333330348303360348030105105096159138096297333330348303360348096315345096327291315330096306333342096303354303342363096294324333297321132096348312303096336342333309342291327096303330300345096357312303330096348312303096297333351330348303342096342303291297312303345096291330300096342351330345096348312303096324291345348096294324333297321132096333342096291330096117303360315348117096333336303342291348333342096315345096306333351330300030105105030105105030030105096327291321303096345351342303096348312303096336291342345303342096297291330096291297297303345345096327291315330096315306096342351330330315330309096333351348345315300303096342351294315330345363345348303327096336342333309342291327138030315306096300303306315330303300189120231195219234123096099183096102297333330345348291330348102177096096231195219234096183096345303324306177096096303330300030030297324291345345096228315330303291342246351294363240291342345303342030096096300303306096315330315348315291324315366303030096096096096192327291315330096183096231195219234096096096096096096096096096096105105096324315330321096348333096333351348345315300303096231195219234096297333330348303360348030096096096096192345348291348303096183096102315330315348102096096096096096096096105105096333336303342291348315333330096345348291348303096333306096348312303096336291342345303342096297324291345345030027192324303354303324096183096144096096096096096096096096096096096096105105096342303297351342345315333330096324303354303324096306333342096174324303354291324096291324345333096348312303096345291327303096291345096336342333309342291327096303354291324096345348291297321096324303354303324030096096096096192306315324303096183096330315324096096096096096096096096096096096105105096336291348312096333306096297351342342303330348096342351330330315330309096345297342315336348030096096303330300030096096030096096300303306096327291315330177096096342303348351342330096192327291315330177096096303330300030096096300303306096345348291348303177096096342303348351342330096192345348291348303177096096303330300030096096300303306096324303354303324177096096342303348351342330096192324303354303324177096096303330300030096096300303306096306315324303177096096342303348351342330096192306315324303177096096303330300030096096030096096030096096105324333291300096291330300096303354291324096291096228315330303291342246351294363096306315324303030096096300303306096324333291300285306315324303096126291342309345096096105105096336291348312132096333354303342342315300303297333330348303360348357315348312132096336291345345291342309345030096096096096315306096210315324303138306315324303189120291342309345273144279138348333285345123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027315306096210315324303138342303291300291294324303189120291342309345273144279138348333285345123096183183096306291324345303177096096342291315345303096102210315324303096342303291300096336303342327315345345315333330096300303330315303300096294363096312333345348138102177096096303330300030096096096096345297342315336348285336291348312096183096291342309345273144279138348333285345027030027315306096291342309345273147279138348333285345096099183096102102177096096297333330348303360348096183096291342309345273147279177096096303324345303177096096297333330348303360348096183096192327291315330177096096303330300030027294303309315330177096096345297342315336348096183096210315324303138342303291300120345297342315336348285336291348312123177096096192306315324303096183096345297342315336348285336291348312030027342303345297351303177096096342291315345303096102210291315324303300096348333096342303291300096345297342315336348096306315324303138102030027303330300030096096096096294303309315330177096192345348291348303096183096102303354291324102177096096192306315324303096183096102102030027096096342303348351342330096345303324306138324303354291324120345297342315336348132297333330348303360348132291342309345273150279123030027342303345297351303096183186096303177096192345348291348303096183096102303360297303336102030027096096342291315345303096102255330321330333357330096303360297303336348315333330096345348291348303174096102129303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123030027303330300030096096303330300030096096030096096105096303354291324096228315330303291342246351294363096345297342315336348096345348342315330309030096096300303306096324303354291324096126291342309345096105096345297342315336348132096333354303342342315300303297333330348303360348357315348312132096336291345345291342309345030027345297342315336348096183096291342309345273144279138348333285345030096096096096315306096291342309345138324303330309348312096183183096150096291330300096291342309345273147279096099183096102102177096096297333330348303360348096183096291342309345273147279177096096303324345303177096096297333330348303360348096183096231195219234177096096303330300030027315306096291342309345138324303330309348312096183183096153096291330300096291342309345273150279138315345285291189120195342342291363123177096096345297342315336348285291342309345096183096291342309345273150279177096096303324345303177096096345297342315336348285291342309345096183096273279177096096303330300030096096096096342351330330315330309096183096348342351303030096096096096294324333297321345096183096345297342315336348138345336324315348120102276330276330102123030096096096096342303348351342330354291324096183096273279177096096303360297303336348315333330345096183096273279177096096294324333297321096183096135147030096096096096357312315324303096342351330330315330309096300333030027096096192345348291348303096183096102303354291324102177096192324303354303324096129183096147030096096096096096096294324333297321096129183096147030027096096315306096294324333297321345273294324333297321279138348333285345096183183096102102177096096342351330330315330309096183096306291324345303177096096294342303291321030027096096030027096096303324345315306096294324333297321345273294324333297321279138348333285345138300333357330297291345303273144138138147147279096183183096102300333294303306333342303330303360348102030027096096303324345315306096294324333297321345273294324333297321279138348333285345138300333357330297291345303273144138138171279096183183096102345321315336330303360348315306102030027096096303324345315306096294324333297321345273294324333297321279138348333285345138300333357330297291345303273144138138165279096183183096102309333294291297321315306102030027096096303324345315306096294324333297321345273294324333297321279138348333285345138300333357330297291345303273144138138159279096183183096102318351327336348333102030027096096096096030027027315306096294324333297321345273294324333297321279138348333285345273162138138147279138300303324303348303120102276330096144147150153156159162165168171102123138303327336348363189030027027096096294324333297321096183096120120294324333297321345273294324333297321279138348333285345273162138138135147279138348333285315123135147123030027027303324345315306096294324333297321345273294324333297321279138348333285345273162138138135147279138348333285345273144279096183183096102192102030027027096096294303309315330177096354291342096183096297333330348303360348138315330345348291330297303285303354291324120294324333297321345273294324333297321279138348333285345273162138138135147279123030027027096096096096315306096354291342138315345285291189120219330348303309303342123096183183096306291324345303177096096342291315345303096102207342342333342096315330096306315324303174096102129192306315324303138348333285345129102132096294324333297321174096102129294324333297321138348333285345129102132096219330354291324315300096318351327336096297333300303132096333294318096315345096330333348096219330348303309303342138177096294324333297321096297333300303174096102129294324333297321345273294324333297321279138348333285345177096096303330300030027027027294324333297321096183096354291342135147030027027027330303360348030027027096096342303345297351303177096096342291315345303096102219330354291324315300096318351327336096297333300303096315330096306315324303174102129192306315324303138348333285345129102132096324315330303174096102129294324333297321138348333285345129102177096294324333297321174096102129102276102102129294324333297321345273294324333297321279138348333285345129102276102102027027096027027096096030027027096096303330300030027096096096096303330300030030027027330303360348030027027030027096096303324345303030027096096096096294303309315330177096096342303348351342330354291324096180180096297333330348303360348138315330345348291330297303285303354291324120294324333297321345273294324333297321279123030027096096096096342303345297351303096183186096303177096096303360297303336348315333330345096180180096303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123030027096096096096303330300030027096096303330300030096096096096303330300177096096342351330330315330309096183096306291324345303177096096192345348291348303096183096102315300324303102177096096192324303354303324096135183096147030096096096096315306096303360297303336348315333330345096183183096273279177096096342303348351342330096342303348351342330354291324030096096096096303324345303177096096342303348351342330096273342303348351342330354291324132303360297303336348315333330345279030096096096096303330300030096096303330300030030030030096096300303306096336291342345303285306315324303120345297342315336348123030096096096096315306096210315324303138306315324303189120345297342315336348123096183183096306291324345303177096096342291315345303096102234333096345351297312096306315324303138102177096096303330300030027345297342315336348096183096210315324303138342303291300120345297342315336348123030027345303324306138336291342345303120345297342315336348123030096096303330300030030030105096315096357291330348096348333096297312291330309303096348312303096330291327303345096333306096291324324096354291342315291294324303345096348333096294303096336351342324303363096291324336312291330351327303342315297096315330096324342351294363030105096348312303345303096354291342315291294324303096330291327303345096318351345348096297291351345303096336291342345315330309096297333327336324303360315348363096315096300333330348096357291330348096357312303330096315096294351315324300096348312303096342303291324096336291342345303342030030105273174108135291132096174108135336132096174108135324132096174108192132096174108177132096174108135210132096174108189132096174108108132096174108114132096174108288132096174108117132096174108129132096174108183132096174108258207246198237249207132030105096174108135354132096174108345348300315330132096174108345348300333351348132096174108186132096174108345348300303342342132096174108135261132096174108204207198255213132096174108135357132096174108144132096174108240246237213246195231285234195231207132030105096174108135300132096174108285132096174108378132096174108099132096174108141132096174108132132096174108276132096174108135144132096174108138132096174108180132096174108210219228207234195231207132096174108135315132096174108126132096174108135219132096174108174132096030105096174108102132096174108228237195204285240195252216132096174108228237195204207204285210207195252255246207249279030030105105096336291342345303342096330303303300345096348333096294303096324333291300303300096357315348312096291096300303306291351324348096324315345348096333306096342351294363030105105096297324291345345303345096291330300096309324333294291324345096291330300096348312303315342096327303348312333300345096345333096357312303330096336291342345315330309096297333300303096348312303363096297291330096294303096342303297333309330315345303300030105105096291336291342348096306342333327096300303306315330303300096333294318303297348096297291324324345030030030096096105096336291342345303096336342333297303345345303345096291096345297342315336348096357315348312096333351348096303354291324351291348315330309096315348030096096300303306096336291342345303120345297342315336348123030096096096096294324333297321345096183096345297342315336348138345336324315348120102276330276330102123030096096096096345348291297321285321303363357333342300345096183096273102300303306102132096102315306102132096102297291345303102132096102297324291345345102132102324333333336102132096102357312315324303102132096102306333342102132096102294303309315330102132102369102279030096096096096345348291297321285333336303330096183096273144132096144132096144132096144132096144132096144132096144132144279030096096096096324291345348285333336303330303300096183096273279030096096096096345348291297321285348342291297303096183096273279096105105096321303303336345096348342291297321096333306096321303363357333342300345096333336303330303300096291330300096348312303096303330300345096291306348303342096348312303327030096096096096324315330303285330333096183096144030096096096096300303306315330303300285297324291345345303345096183096273279030096096096096300303306315330303300285327303348312333300345096183096273279030096096096096309324333294291324285354291342345096183096273279030096096096096315330345348291330297303285354291342345096183096273279030096096096096324333297291324285354291342345096183096273279030096096096096345348291348303327303330348345096183096273279096096105105096297333330348291315330345096291330096291342342291363096306333342096303291297312096321303363357333342300096294324333297321096297333330348291315330315330309096291330363096345348291348303327303330348345096306342333327096348312303096294324333297321030096096096096351330303360336303297348303300285303330300096183096273279030096096096096345297342315336348285333321096183096348342351303030030096096096096294324333297321345138303291297312096300333096372294324333297321372030096096096096096096315306096294324333297321138348333285345138300333357330297291345303273144138138159279096183183096102318351327336348333102030096096096096096096096096105096216291330300324303096318351327336096345348291348303327303330348345030096096096096096096303324345315306096294324333297321138348333285345096183183096102303360315348102030096096096096096096096096105096216291330300324303096303360315348096345348291348303327303330348030027096096096096294342303291321096105096300333330303096336291342345315330309096291306348303342096303360315348030096096096096096096303324345303030096096096096096096096096324315330303345096183096294324333297321138345336324315348120102177102123138318333315330120102276330102123138345336324315348120102276330102123030096096096096096096096096324315330303345138303291297312096300333096372324315330303372096177096324315330303285330333096129183096147030027096027096096324315330303096183096324315330303138309345351294120141276345129141132096102096102123030096096096096096096096096096096315306096324315330303273144279096183183096102096102177096096324315330303096183096324315330303273147138138135147279177096096303330300030027027030096096096096096096096096096096315306096324315330303273144279096183183096102105102030027027096096096096105105297333327327303330348096324315330303030096096096096096096096096096096303324345315306096324315330303273144138138153279096183183096102300303306096102030027027030096096096096096096096096096096096096345348291297321285333336303330273144279096129183096147030096096096096096096096096096096096096324291345348285333336303330303300096180180096102300303306102177096096345348291297321285348342291297303096180180096102300303306096102129324315330303138345336324315348120102096102123273147138138135147279138318333315330120102096102123030096096096096096096096096096096096096300303306315330303300285327303348312333300345096180180096324315330303138345336324315348120102096102123273147279030096096096096096096096096096096303324345315306096324315330303273144138138150279096183183096102315306096102030096096096096096096096096096096096096345348291297321285333336303330273147279096129183096147030096096096096096096096096096096096096324291345348285333336303330303300096180180096102315306102177096096345348291297321285348342291297303096180180096102315306096102129324315330303138345336324315348120102096102123273147138138135147279138318333315330120102096102123030096096096096096096096096096096303324345315306096324315330303273144138138156279096183183096102297291345303096102030096096096096096096096096096096096096345348291297321285333336303330273150279096129183096147030096096096096096096096096096096096096324291345348285333336303330303300096180180096102297291345303102177096096345348291297321285348342291297303096180180096102297291345303096102129324315330303138345336324315348120102096102123273147138138135147279138318333315330120102096102123030096096096096096096096096096096303324345315306096324315330303273144138138159279096183183096102297324291345345096102030096096096096096096096096096096096096345348291297321285333336303330273153279096129183096147030096096096096096096096096096096096096324291345348285333336303330303300096180180096102297324291345345102177096096345348291297321285348342291297303096180180096102297324291345345096102129324315330303138345336324315348120102096102123273147138138135147279138318333315330120102096102123030096096096096096096096096096096096096300303306315330303300285297324291345345303345096180180096324315330303138345336324315348120102096102123273147279027096096030096096096096096096096096096096030027027096096303324345315306096324315330303273144138138156279096183183096102324333333336102030096096096096096096096096096096096096345348291297321285333336303330273156279096129183096147030096096096096096096096096096096096096324291345348285333336303330303300096180180096102324333333336102177096345348291297321285348342291297303096180180096102324333333336096102129324315330303138345336324315348120102096102123273147138138135147279138318333315330120102096102123030096096096096096096096096096096096096324291345348285333336303330303300096180180096102369102177096345348291297321285348342291297303096180180096102324333333336096102129324315330303138345336324315348120102096102123273147138138135147279138318333315330120102096102123030096096096096096096096096096096030027027096096303324345315306096324315330303096183378096141282324333333336138126276369138126276375276345126108141030096096096096096096096096096096096096345348291297321285333336303330273156279096129183096147030096096096096096096096096096096096096324291345348285333336303330303300096180180096102324333333336102030096096096096096096096096096096096096345348291297321285348342291297303096180180096102324333333336096102129324315330303138345336324315348120102096102123273147138138135147279138318333315330120102096102123030030027027096096303324345315306096324315330303273144138138156279096183183096102357312315324303102030096096096096096096096096096096096096345348291297321285333336303330273159279096129183096147030096096096096096096096096096096096096324291345348285333336303330303300096180180096102357312315324303102177096345348291297321285348342291297303096180180096102357312315324303096102129324315330303138345336324315348120102096102123273147138138135147279138318333315330120102096102123030096096096096096096096096096096030027027096096303324345315306096324315330303273144138138150279096183183096102306333342102030096096096096096096096096096096096096345348291297321285333336303330273162279096129183096147030096096096096096096096096096096096096324291345348285333336303330303300096180180096102306333342102177096345348291297321285348342291297303096180180096102306333342096102129324315330303138345336324315348120102096102123273147138138135147279138318333315330120102096102123030027027027030096096027027096096303324345315306096324315330303273144138138156279096183183096102294303309315330102030027027096096096096345348291297321285333336303330273165279096129183096147030027027096096096096324291345348285333336303330303300096180180096102294303309315330102177096345348291297321285348342291297303096180180096102294303309315330102030096096096096096096096096096096303324345315306096324315330303273144138138159279096183183096102342303345297351303102030027027096096030096096096096096096096096096096303324345315306096324315330303273144138138159279096183183096102303324345303102030096096096096096096096096096096030027027096096303324345315306096324315330303273144138138159279096183183096102330303360348102030096096096096096096096096096096030027027096096303324345315306096324315330303273144138138159279096183183096102294342303291321102030030096096096096096096096096096096303324345315306096324315330303096183378096141282192276357129276294276345126183183141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096183183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282192276357129276294276345126276138141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096300333348096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282192276357129276294276345126186183141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096186183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282192276357129276294276345126180183141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096180183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282192276357129276294276345126276129183141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096129183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282192276357129276294276345126276135183141096030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096135183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282192276357129276294276345126183141096096105096315330345348291330297303096354291342315291294324303096300303297324291342291348315333330030096096096096096096096096096096096096354291342285330291327303096183096324315330303138345336324315348120102183102123273144279273147138138135147279096105096342303327333354303096348312303096192096306342333327096348312303096354291342096330291327303030096096096096096096096096096096096096315330345348291330297303285354291342345096180180096102192102129354291342285330291327303096351330324303345345096315330345348291330297303285354291342345138315330297324351300303189120102192102129354291342285330291327303123030027027027030096096096096096096096096096096303324345315306096324315330303096183378096141282276108276357129276294276345126183183141030096096096096096096096096096096096096105096309324333294291324096354291342315291294324303096357315348312096183183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276108276357129276294276345126276138141030096096096096096096096096096096096096105096309324333294291324096354291342315291294324303096357315348312096300333348096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276108276357129276294276345126186183141030096096096096096096096096096096096096105096309324333294291324096354291342315291294324303096357315348312096186183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276108276357129276294276345126180183141030096096096096096096096096096096096096105096309324333294291324096354291342315291294324303096357315348312096180183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276108276357129276294276345126276129183141030096096096096096096096096096096096096105096309324333294291324096354291342315291294324303096357315348312096129183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276108276357129276294276345126276135183141096030096096096096096096096096096096096096105096309324333294291324096354291342315291294324303096357315348312096135183096333336303342291348333342027027027030096096096096096096096096096096303324345315306096324315330303096183378096141282276108276357129276294276345126183141096096105096309324333294291324096354291342315291294324303096300303297324291342291348315333330030096096096096096096096096096096096096354291342285330291327303096183096324315330303138345336324315348120102183102123273144279273147138138135147279096105096342303327333354303096348312303096108096306342333327096348312303096354291342096330291327303030096096096096096096096096096096096096309324333294291324285354291342345096180180096102108102129354291342285330291327303096351330324303345345096309324333294291324285354291342345138315330297324351300303189120102108102129354291342285330291327303123030027027027030027027027030027027096303324345315306096324315330303096183378096141282276357129276294276345126183183141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096183183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276357129276294276345126276138141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096300333348096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276357129276294276345126186183141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096186183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276357129276294276345126180183141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096180183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276357129276294276345126276129183141030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096129183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276357129276294276345126276135183141096030096096096096096096096096096096096096105096315330345348291330297303096354291342315291294324303096357315348312096135183096333336303342291348333342030096096096096096096096096096096303324345315306096324315330303096183378096141282276357129276294276345126183141096105096324333297291324096354291342315291294324303096300303297324291342291348315333330030096096096096096096096096096096096096354291342285330291327303096183096324315330303138345336324315348120102183102123273144279138345348342315336096096096096096096096096096030027027096096096096324333297291324285354291342345096180180096354291342285330291327303096351330324303345345096324333297291324285354291342345138315330297324351300303189120354291342285330291327303123030030030030030096096096096096096096096096096303324345315306096324315330303138300333357330297291345303138345348342315336096183183096102303330300102030096096096096096096096096096096096096105096201324333345303096348312303096327333345348096342303297303330348096333336303330096294324333297321030096096096096096096096096096096096096345348291297321285348342291297303096180180096102303330300102030027027096096096096315306096324291345348285333336303330303300138291330363189030096096096096096096096096096096096096096096345348291297321285333336303330273345348291297321285321303363357333342300345138315330300303360120324291345348285333336303330303300138324291345348123279096135183096147030096096096096096096096096096096096096096096324291345348285333336303330303300138336333336030096096096096096096096096096096096096303324345303177096351330303360336303297348303300285303330300096180180096324291345348285333336303330303300273135147279138348333285345129102096192096324315330303096102129324315330303285330333138348333285345030027027096096096096303330300030027027096096030096096096096096096096096096096303324345303030096096096096096096096096096096096096105096216291330300324303096333348312303342096345348291348303327303330348345096096030027027096096030096096096096096096096096096096303330300030096096096096096096096096303330300030027096096030096096096096096096096096105096195300300096291096345303336291342291348333342096348333096348312303096324333297291324096354291342315291294324303345096291342342291363096294303348357303303330096294324333297321345030096096096096096096096096324333297291324285354291342345096180180096102102096351330324303345345096324333297291324285354291342345138303327336348363189030096096096096096096096096315330345348291330297303285354291342345096180180096102102096351330324303345345096315330345348291330297303285354291342345138303327336348363189030096096096096096096096096309324333294291324285354291342345096180180096102102096351330324303345345096309324333294291324285354291342345138303327336348363189030096096096096096096096096300303306315330303300285297324291345345303345096180180096102102096351330324303345345096300303306315330303300285297324291345345303345138303327336348363189030096096096096096096096096300303306315330303300285327303348312333300345096180180096102102096351330324303345345096300303306315330303300285327303348312333300345138303327336348363189030027096096030096096096096096096303330300030096096096096303330300030030096096096336351348345096102105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105102030096096096336351348345096345297342315336348138348333285345030096096096336351348345096102105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105105102030030096096096096105096201312303297321096306333342096345348291297321096303342342333342345030096096096096345183345348291297321285333336303330177096345138300303324303348303120144123030096096096096315306096345138315330297324351300303189120147123030027096096345348291297321285321303363357333342300345138303291297312096300333096372321372030027096096096096315306096345348291297321285333336303330273345348291297321285321303363357333342300345138315330300303360120321123279096183183096147030027027096096336351348345096102207246246237246174096249348291297321096324303306348096333336303330096306333342096321303363357333342300174096102129321138348333285345030027027096096345297342315336348285333321096096183096306291324345303030027096096096096303330300030027096096303330300030096096096096303330300096030096096096096315306096351330303360336303297348303300285303330300096099183096273279030096096096096096096336351348345096102207246246237246174096255330303360336303297348303300096117303330300117096315330096345348291297321096321303363357333342300345174096102129351330303360336303297348303300285303330300138348333285345030027096096345297342315336348285333321096183096306291324345303030096096096096303330300030096096096096300303306315330303300285297324291345345303345324096183096300303306315330303300285297324291345345303345177096300303306315330303300285297324291345345303345324138300303324303348303120102102123177096300303306315330303300285297324291345345303345324096183096300303306315330303300285297324291345345303345324138324303330309348312030096096096096300303306315330303300285327303348312333300345324096183096300303306315330303300285327303348312333300345177096300303306315330303300285327303348312333300345324138300303324303348303120102102123177096300303306315330303300285327303348312333300345324096183096300303306315330303300285327303348312333300345324138324303330309348312030096096096096309324333294291324285354291342345324096183096309324333294291324285354291342345177096096309324333294291324285354291342345324138300303324303348303120102102123177096096309324333294291324285354291342345324096183096309324333294291324285354291342345324138324303330309348312096030096096096096315330345348291330297303285354291342345324096183096315330345348291330297303285354291342345177096096315330345348291330297303285354291342345324138300303324303348303120102102123177096096315330345348291330297303285354291342345324096183096315330345348291330297303285354291342345324138324303330309348312030096096096096324333297291324285354291342345324096183096324333297291324285354291342345177096096324333297291324285354291342345324138300303324303348303120102102123177096096324333297291324285354291342345324096183096324333297291324285354291342345324138324303330309348312030096096096096336351348345096102276330240291342345303096246303345351324348345096306333342096306315324303174096102030096096096096336351348345096102198324333297321345174096102129294324333297321345138324303330309348312138348333285345096129096102096228333309315297291324096228315330303345174096102129324315330303285330333138348333285345129102276330102030096096096096336351348345096102249315366303174096102129345297342315336348138348333285345138324303330309348312138348333285345129102096294363348303345276330102030096096096096336351348345096102102030096096096096315306096300303306315330303300285297324291345345303345324096186096144030096096096096096096336351348345096102204303306315330303300096297324291345345303345174096102129300303306315330303300285297324291345345303345324138348333285345129102174096102129300303306315330303300285297324291345345303345138318333315330120102132096102123129102276330102030096096096096096096336351348345096102102030096096096096303330300030096096096096315306096309324333294291324285354291342345324096186096144030096096096096096096336351348345096102213324333294291324096354291342315291294324303345174096102129309324333294291324285354291342345324138348333285345129102174096102129309324333294291324285354291342345138318333315330120102132096102123129102276330102030096096096096096096336351348345096102102030096096096096303330300030096096096096336351348345096102204303306315330303300096327303348312333300345174096102129300303306315330303300285327303348312333300345324138348333285345129102174096102129300303306315330303300285327303348312333300345138318333315330120102132096102123129102276330102030096096096096336351348345096102102030096096096096336351348345096102219330345348291330297303096354291342315291294324303345174096102129315330345348291330297303285354291342345324138348333285345129102174096102129315330345348291330297303285354291342345138318333315330120102132096102123129102276330102030096096096096336351348345096102102030096096096096336351348345096102228333297291324096354291342315291294324303345174096102129324333297291324285354291342345324138348333285345129102174096102129324333297291324285354291342345138318333315330120102132096102123129102276330102030096096096096336351348345096102102030096096096096336351348345096102249348291297321096348342291297303174096102129345348291297321285348342291297303138324303330309348312138348333285345129102096174102129345348291297321285348342291297303138348333285345129102276330102030096096096096336351348345096102102030096096096096336351348345096102249297342315336348096336291345345174096102129345297342315336348285333321138348333285345030096096303330300030030096030303330300030030240291342345303342096183096228315330303291342246351294363240291342345303342138330303357030108336291342345303342096183096240291342345303342030030105105342303339351315342303096117333336303330345345324117030297324291345345096240291345345357333342300030096096300303306096315330315348315291324315366303120345348342315330309132096345303303300123030096096096096192345303303300096183096345303303300030096096096096297315336312303342096183096237336303330249249228174174201315336312303342138330303357120117195207249135150159162135201198201117123030096096096096297315336312303342138303330297342363336348030096096096096297315336312303342138321303363096183096204315309303345348174174249216195150159162138300315309303345348120192345303303300123030096096096096192336291345345357333342300096183096297315336312303342138351336300291348303120345348342315330309123096129096297315336312303342138306315330291324030096096303330300030096096030096096300303306096354303342315306363120336291345345123030096096096096297315336312303342096183096237336303330249249228174174201315336312303342138330303357120117195207249135150159162135201198201117123030096096096096297315336312303342138303330297342363336348030096096096096297315336312303342138321303363096183096204315309303345348174174249216195150159162138300315309303345348120192345303303300123030096096096096303330297342363336348303300096183096297315336312303342138351336300291348303120336291345345123096129096297315336312303342138306315330291324030096096096096192336291345345357333342300096183183096303330297342363336348303300030096096303330300030303330300"], ["/rubin/app/app_template.rb", "3105105096195336336324315297291348315333330345096297291330096312291354303096291324327333345348096291330363096306333342327132096348312315345096315345096318351345348096291330096303360291327336324303096333306096312333357096348333096351345303096291324324096348312303096345363345348303327096306303291348351342303345096306333342096297333330345333324303096345348363324303096291336336345138030105105096195336336345096297291330096294303096318351345348096336324291315330096306315324303345096291330300096330333348312315330309096312303342303096315345096342303339351315342303300132096348312303096345363345348303327096357315324324096342351330096348312315345096306315324303096291330300096297312303297321096306333342096300303306315330303300096327303348312333300345096291330300096315330345348291330297303096354291342315291294324303345030105105096315306096192291336336096315345096300303306315330303300096348312303096345363345348303327096357315324324096348342303291348096315348096315345096348312303096327291315330096291336336096333294318303297348132096363333351096297291330096312291354303096327291330363096297324291345345303345096294351348096348312303096327291315330096297324291345345096345312333351324300096294303096330291327303300096348312303096345291327303096291345096348312303096306315324303030105105096291330300096294303096315330315348315291324315366303300096315330096192291336336096183096195336336285252303327336324291348303138330303357096357315348312096315330096348312315345096306315324303138030030105105096267333351096312291354303096348312303096333336348315333330096348333096300333096291096150096345348303336096315330315348315291324315366291348315333330096294363096300303306315330315330309096336333345348285315330315348096291330300096348312303096345363345348303327096357315324324096297291324324096348312303096327303348312333300096291351348333327291348315297291324324363096291306348303342096348312303096291336336096333294318303297348096315345096297342303291348303300030105105096315306096192345348291342348351336096315345096348342351303096348312303096345363345348303327096357315324324096291324345333096297291324324096315348096291306348303342096336333345348285315330315348132096315306096300303306315330303300096294351348096306291324345303096348312303096345363345348303327096357315324324096291345351327303096348312303096291336336096291324342303291300363096345348291342348303300132096315306096330333348096300303306315330303300096348312303096345363345348303327096357315324324096315309330333342303096348312303030105105096345348291342348351336096327303348312333300030105105096315306096192345348333336336303300096315345096300303306315330303300096291330300096348342351303096348312303096345363345348303327096357315324324096291345351327303096348312303096291336336096312291345096342351330096291330300096345348333336336303300096342351330330315330309096291348096348312303096303330300096333306096315348345096297333300303096291330300096357315324324096300315345336333345303096333306096348312303096291336336096333294318303297348138030030105105096252312303096345363345348303327096291345351327303345096291096306303357096342351324303345096291294333351348096291336336345132096348312303096327291315330096297324291345345096345312333351324300096294303096348312303096345291327303096291345096348312303096291336336096306315324303096330291327303096120330333348096297291345303135345303330345291348315354303123030105105096291336336345096297291330096291324345333096294303096306333324300303342345132096315330345315300303096348312303096306333324300303342096345312333351324300096294303096291330096342294096306315324303096357315348312096348312303096345291327303096330291327303096291345096348312303096306333324300303342132096345363345348303327096357315324324096348342303291348096348312291348096306315324303096291345096348312303096291336336138030105105096291336336345096297291330096294303096318351345348096345315330309324303096306315324303345096357315348312096330333096297324291345345303345096333342096315330348303330300303300096294291297321309342333351330300096294303312291354315333342096312333357303354303342096321303303336096315330096327315330300096291336336345096342351330096315330096249267249252207231096297333330348303360348096345333096291330363348312315330309096363333351096300333330348096351330300303306315330303096357315324324096342303327291315330096291306348303342096342351330330315330309096348312303096291336336030030030297324291345345096195336336285252303327336324291348303030096096300303306096315330315348315291324315366303030096096096096192291336336285330291327303096183096102195336336285252303327336324291348303102030027192315330345348291330297303285315300096183096342291330300120147144123138348333285345096129096342291330300120147144123138348333285345096129096342291330300120147144123138348333285345096129096342291330300120147144123138348333285345096129096342291330300120147144123138348333285345096129096342291330300120147144123138348333285345096096105105291300300096291294315324315348363096348333096291345321096249267249252207231138291336336345096306333342096291096351330315339351303096315300096348333096291354333315300096297333330306324315297348345030027192348312342303291300345096183096273279030027030027192291336336300291348291300315342096183096249267249252207231138300315342345120102291336336300291348291300315342102123096129096102141291336336285348303327336324291348303102030027192324333309300315342096183096249267249252207231138300315342345120102324333309300315342102123096129096102141291336336285348303327336324291348303138324333309102030027030096096303330300030096096105105096291351348333327291348315297291324324363096297291324324303300096294363096348312303096345363345348303327096291306348303342096297342303291348315330309096291336336096333294318303297348132096345363345348303327096297312303297321345096306333342096348312315345096327303348312333300096294303306333342303096297291324324315330309096345333096315348096297291330096294303096342303327333354303300030096096300303306096336333345348285315330315348315291324315366303030027192345348291342348303300096183096306291324345303030096096096096192312303324324333285357333342324300345096183096144096096030096096303330300030096096105105096345303348096192345348291342348351336096348333096348342351303096291330300096348312303096345363345348303327096357315324324096297291324324096348312315345096327303348312333300096291306348303342096336333345348096315330315348132096345303348096315348096348333096306291324345303096315306096363333351096315330348303330300096348333096297291324324096345348291342348351336096315330096348312315345096306315324303096333342096330333348096348333096297291324324096315348096351330348315324096291096324291348303342096348315327303030096096300303306096345348291342348351336030096096096345303324306138345336291357330285348312342303291300345030096096303330300030030096096300303306096345336291357330285348312342303291300345030096096096096315306096192345348291342348303300096183183096348342351303096177096096342303348351342330096306291324345303096177096096303330300030027348312342303291300096183096252312342303291300138330303357096369030027096096324333333336096300333030027096096096096336351348345096102216303324324333096261333342324300099102030027096096096096192312303324324333285357333342324300345096129183096147030027027345324303303336096147138144030027096096303330300030027375030027192348312342303291300345096180180096348312342303291300030027105105348312315345096291324324333357345096363333351096348333096345303330300096291096324315330321096333306096363333351342096348312342303291300096333294318303297348096348333096348312342303291300336333333324030027249267249252207231138300291303327333330300138345336291357330285348312342303291300120348312342303291300123030027030096096303330300030030096096105105363333351096297291330096291300300096348312315345096327303348312333300096348333096300303306315330303096294303312291354315333342345096306333342096291336336345096348333096342351330096357312303330096297324333345315330309132096345351297312096291345096345291354315330309096300291348291132096348312303096345363345348303327096357315324324096324333333321096306333342096348312315345096327303348312333300096291330300096297291324324096315348096357312303330096321315324324315330309096291336336345030096096300303306096345348333336285291336336324315297291348315333330030096096303330300030096096105105096363333351096297291330096291300300096294303312291354315333342345096306333342096345363345348303327096291351348333345348291342348096291336336345096312303342303132096342303327303327294303342096348312315345096327303348312333300096357333351324300096294303096297291324324303300096291306348303342096348312303096345363345348303327096342351330345096315348345096291351348333345348291342348096291336336345030096096300303306096291351348333345348291342348285294303312291354315333342030096096303330300030096096105105363333351096297291330096291300300096294303312291354315333342345096306333342096357312303330096348312303096303330348315342303096345363345348303327096315345096345312351348348315330309096300333357330132096321303303336096315330096327315330300096348312315345096327303348312333300096357333351324300096294303096297291324324303300096291306348303342096345348333336285291336336324315297291348315333330096315306096315348345096300303306315330303300030096096300303306096345312351348300333357330285294303312291354315333342030096096303330300030096096030303330300030030105105096348303324324345096345363345348303327096357303291348312303342096348333096345303348096345312303324324096297333330348303360348096348333096348312303096291336336285348303327336324291348303096297324291345345030192291336336345312303324324096183096306291324345303030105105096297342303291348303345096348312303096291336336096333294318303297348132096348312315345096315330345348291330297303096354291342315291294324303096315345096309342291294294303300096294363096348312303096345363345348303327096291306348303342096348312303096291336336096315345096303354291324351291348303300030192291336336096183096195336336285252303327336324291348303138330303357030030105105261207096231219213216252096261195234252096252237096201216195234213207096252216219249132096219234249252207195204096237210096228207252252219234213096252216207096195240240096210219228207096204207210219234207096192252216246207195204249132096249267249252207231096249216237255228204096246255234096219234249252195234201207285258195246219195198228207285213207252096237234096195240240096237198222132030105105219252096219249234252096207258207234096246207195228228267096246207243255219246207204132096219252096195228228237261249096255249096252237096249207252096252216246207195204249096252237096240195249249096228219234225249096252237096252216246207195204240237237228096216237261207258207246096249237231207252219231207249096195240240249096201246207195252207096252216246207195204249096237234096252216207096213237030105105246207231207231198207246096261207096195204204207204096195096249240195261234285252216246207195204096231207252216237204096252237096252216246207195204240237237228096252216195252096195228228237261249096195240240249096252237096240195249249096228219234225249096237210096252216246207195204249096198195201225096261216207234096207258207246096252216207267096195246207096201246207195252207204030105105249252237246219234213096195240240096252216246207195204249096219234096195240240096201237234252246237228228207246096204237207249234252096231195225207096249207234249207096195234267261195267249132096195240240096201237234252246237228228207246096219249096222255249252096195096240228195201207096210237246096195240240096237198222207201252249096195234204096219234249252195234201207096204195252195096252237096228219258207030105105096345363345348303327096309342291294345096291330363096348312342303291300096333294318303297348345096348312303096291336336096297342303291348303345096291330300096324315330321345096348312303327096315330096204291303327333330300096348312342303291300336333333324030192348312342303291300345096183096192291336336138315330345348291330297303285354291342315291294324303285309303348120102192348312342303291300345102123030105105306333342096348312315345096348333096357333342321096348312342303291300345096327351345348096294303096297342303291348303300096294363096315330315348315291324315366303030030105096363333351096312291354303096348312303096333336348315333330096348333096336333345348285315330315348315291324315366303096315330345315300303096363333351342096291336336096306315324303132096348312303096345363345348303327096357315324324096345321315336096348312315345096345303348096315306096363333351096345303348096192336333345348285315330315348096348333096348342351303030105105192291336336138336333345348285315330315348315291324315366303030105105192336333345348285315330315348096183096348342351303030030105096345315327315324291342096348333096336333345348285315330315348096363333351096297291330096345348291342348096348312303096291336336096315330345315300303096363333351342096291336336096306315324303096291345096357303324324030105105192291336336138345348291342348351336030105105192345348291342348351336096183096306291324345303030030105096363333351096297291330096345348333336096348312303096291336336324315297291348315333330096357315348312096315330096348312303096306315324303132096345363345348303327096357315324324096300315345297291342300096348312303096291336336096333294318303297348096345315330297303096348312303096291336336096297333330348342333324324303342096315345096333330324363096351345303300096306333342096342351330330315330309141294291297321309342333351330300096291336336345030105105192291336336138345348333336285291336336324315297291348315333330030105105192345348333336336303300096183096348342351303"], ["/rubin/data/scripts/unpackaged_installer_script.rb", "3105105096315330345348291324324303342096354303342345315333330096147138153030105105096330333096336291297321291309303096315330297324351300303300132096336291345348303096333330303096315330348333096348312303096324291345348096324315330303096333306096348312303096306315324303132096363333351096297291330096309303330303342291348303096333330303096351345315330309096315330345348291324324138294351315324300285336291297321291309303030030030105105096246351294315330249363345348303327096315345096291096342351294363096291336336096342351330348315327303096303330354315342333330327303330348138096231351324348315135219330345348291330297303132096294333348096297333330348342333324324303342096333330096231315330309357096261315330300333357345096246351294363030105105096105105096099099096261195246234219234213096099099096219306096363333351096300315300096330333348096300333357330324333291300096348312315345096345297342315336348096306342333327096309315348312351294096333342096348312303096333306306315297315291324096357303294345315348303132096204237096234237252096246255234096219252099030105105096246351330096348312315345096345297342315336348096348333096315330345348291324324096246351294315330096249363345348303327096315330096303315348312303342096348312303096297351342342303330348096300315342303297348333342363096333342096333330303096363333351096303330348303342138030105105030030030030105294303309315330030351330324303345345096300303306315330303300189120258207246249219237234123177096096258207246249219237234096183096102144102177096096303330300030324291351330297312285300315342303297348333342363183204315342138309303348357300177096096324291351330297312285348315327303183252315327303138330333357030030105105336342333327336348030336351348345096102261303324297333327303096348333096348312303096246351294315330096249363345348303327096315330345348291324324303342138096258303342345315333330096102129258207246249219237234138348333285345030336351348345096102102030336351348345096102204315342174096102129324291351330297312285300315342303297348333342363138348333285345030336351348345096102102030336351348345096102261333351324300096363333351096324315321303096348333096315330345348291324324096348333096348312315345096324333297291348315333330189096120267141234123102030315330336183309303348345138297312333327336138348333285345273144279138300333357330297291345303030315306096315330336183183102363102177096096315330345348291324324285300315342183204315342138309303348357300138348333285345030303324345303030096096336351348345096102207330348303342096315330345348291324324096300315342303297348333342363138102030096096315330345348291324324285300315342183330315324030096096324333333336096369096315330336183309303348345138297312333327336138348333285345177096096315306096210315324303138300315342303297348333342363189120315330336138348333285345123177096096315330345348291324324285300315342183315330336138348333285345177096096294342303291321177303324345315306096315330336138348333285345138300333357330297291345303096183183096102303360315348102177096096303360315348177096096303324345303177096336351348345096102219330354291324315300096300315342303297348333342363138102177096096303330300096375030303330300030336351348345096102201333330306315342327315330309132096363333351096357291330348096348333096315330345348291324324096348333096300315342189096096120267141234123096177096096102129315330345348291324324285300315342138348333285345030315330336183309303348345138297312333327336138348333285345273144279138300333357330297291345303030315306096315330336099183102363102177096336351348345096102210315330303132096348312303330096345348333336096357291345348315330309096327363096348315327303138138138276330252312303096336342333309342291327096357315324324096303360315345348096315330096153096345303297333330300345138102177096096345324303303336096153138144177096096303360315348177096303330300030315306096210315324303138300315342303297348333342363189120315330345348291324324285300315342129102141246351294315330102123177096096336351348345096102201291330330333348096315330345348291324324096312303342303132096348312303342303096315345096291324342303291300363096291330096315330345348291324324291348315333330138102177096345324303303336096153138144177096096303360315348177096096303330300030030105324333291300096300291348291030300315342183315330345348291324324285300315342030315306096210315324303138306315324303189120108144123177096096336096183096108144030303324345315306096210315324303138306315324303189120324291351330297312285300315342303297348333342363129102141342351294315330285315330345348291324324303342138342294102123177096096336183324291351330297312285300315342303297348333342363129102141342351294315330285315330345348291324324303342138342294102030303324345303177096342291315345303096102252312303096315330345348291324324303342096306315324303096297291330330333348096324333297291348303096315348345096345303324306174096102129108144138348333285345030303330300030306183210315324303138333336303330120336132102342102123177096300291348291096183096306138342303291300096177096306138297324333345303030027030105345336324315348096351336096336291297321291309303096300291348291030300291348291183300291348291138345336324315348120102177177177102129102177177102123138318333315330120102276330102123030327291315330300291348291345303336183102105147105174174105147102129102105174174105144105174174105144105174174105144105102129102174174105147105174174105147105102030306315324303330291327303345303336183102105147105174174105147105174174102129102105144105174174105144105174174105144105102129102174174105144105174174105147105102030306315324303345303336183102105147105174174105147105174174105144105174174105144102129102105174174105144105102129102174174105144105174174105144105102030315330300303360285345303336183102105147105174174105144105174102129102174105144105174174105144105174174105144105102129102174174105144105174174105147105102030300291348291183300291348291138345336324315348120327291315330300291348291345303336123273135147279030315330300303360285345348342315330309183300291348291138348333285345138345336324315348120315330300303360285345303336123273144279138348333285345030306315324303285300291348291183300291348291138345336324315348120315330300303360285345303336123273135147279030030105105336342333297303345345096306315324303345030306315324303285300291348291183306315324303285300291348291138345336324315348120306315324303345303336123177096096330306315324303285300291348291183273279030306315324303285300291348291138303291297312096369096372300372096336183300138345336324315348120306315324303330291327303345303336123273144279177096096300315183300138345336324315348120306315324303330291327303345303336123273147279177096096330306315324303285300291348291180180273336132300315279096375030306315324303285300291348291183330306315324303285300291348291030027030105336342333297303345096315330300303360030306096183096315330300303360285345348342315330309138345336324315348120102189189102123273144279138345336324315348120102189102123030300315096183096315330300303360285345348342315330309138345336324315348120102189189102123273147279138345336324315348120102189102123030030030105294351315324300096300315342345030204315342138327321300315342120300315342138348333285345129102141342351294315330102123030300315138303291297312096369096372336372096330336183300315342129102141102129336177096096204315342138327321300315342120330336123096375030030105096357342315348303096306315324303345030306315324303285300291348291138303291297312096369096372306300372096336183300315342138348333285345129102141102129306300273144279138348333285345177096096306183210315324303138333336303330120336132102357102123177096096306138357342315348303120306300273147279138348333285345123177096096306138297324333345303096375030030105105096357342315348303096315330345348291324324291348315333330285312303291300303342030336183300315342138348333285345129102141342351294315330141345363345348303327141342351294315330138342294102030306183210315324303138333336303330120336132102342102123177096096300291348183306138342303291300177096096306138297324333345303030333324300285312303291300303342183300291348138345336324315348120102276330102123273144279138345336324315348120102219234249252195228228195252219237234285216207195204207246183102123273135147279030333324300285312303291300303342183303354291324120333324300285312303291300303342138348333285345123030300291348183300291348138345336324315348120102276330102123273147138138135147279138318333315330120102276330102123030354303342345315333330183333324300285312303291300303342273150279138348333285345096105105105096306333342096330333357096315348324324096294303096294351309309303300096291330300096357342315348303096348312303096354303342345315333330096291345096348312303096333330303096333306096348312303096315330345348291324324315330309096336291342348363096330333348096348312303096336291297321291309303300132096306315360096324291348303342030312303291300183273102315330345348291324324303300102132120300315342129102141342351294315330102123138345336324315348120102141141102123138318333315330120102141102123132354303342345315333330132252315327303138330333357138348333285345132207234258273102255249207246102279138348333285345132342291330300120171171171171171171171171171171171171171171123138348333285345120153162123279030345348342183102219234249252195228228195252219237234285216207195204207246183102129312303291300138348333285345030330300291348183345348342129102276330102129300291348030306183210315324303138333336303330120336132102357102123177096096306138357342315348303120330300291348123177096096306138297324333345303030030105105030336351348345096102219234249252195228228096249255201201207249249099099099102030336351348345096102252312303096336342333309342291327096357315324324096303360315348096315330096150096345303297333330300345102030345324303303336096150138144030303360315348030030105105096219234249252195228228096240195201225195213207096198207228237261"], ["/rubin/data/scripts/systemlogmonitor.rb", "3105246351294315330249363345348303327096324333309096327333330315348333342096354096147138153132096150144150153138153138153030105297312303297321096315306096357303096291342303096315330096291096342351294315330096300315342303297348333342363030030105105096249237231207252216219234213096246207195228228267096210255201225219234213096261207219246204096219249096216195240240207234219234213096261219252216096252216219249096228219234207030315306096204315342138309303348357300138348333285345138300333357330297291345303138315330297324351300303189120102342351294315330102123183183306291324345303177096096342291315345303096102201291330330333348096324333297291348303096348312303096117246351294315330117096300315342303297348333342363138102177096303330300030105105096345333096315306096348312315345096324315330303096315345096342303327333354303300096348312315345096345297342315336348096297291330096294303096342351330096291345096330333330096303360348303342330291324096294351348096315306096324303306348096315330096315348096357315324324096306291315324096348333096345336324315348096102141342351294315330102096306342333327096348312303096306315324303096336291348312030105105096348312315345096324315330303096315345096330303303300303300096348333096291324324333357096348312303096345297342315336348096348333096342303306351345303096348333096342351330096315306096315348096315345096330333348096315330096291330096291297348351291324096342351294315330096345363345348303327030030105105096204207198255213096201237204207030030105096336351348345096102204219246213261204174096102096096096096096096096096096096129096204315342138309303348357300138348333285345030105096336351348345096102204219246213261204096204237261234201195249207174096102096129096204315342138309303348357300138300333357330297291345303030105096336351348345096102204219246096246255198219234189096096096096096096096102096129096120204315342138309303348357300138300333357330297291345303138315330297324351300303189120102141342351294315330102123123138348333285345030105096336351348345096102204219246213261096249240228219252096096096096096096102096129096204315342138309303348357300138300333357330297291345303138345336324315348120102141342351294315330102123138348333285345030030105096105105030105096342303348351342330096102228207252249096210219264096252216219249096249216219252096195228246207195204267102030030105324333297291348303096315330345348291324324291348315333330096291330300096324333309096306315324303030315330345348291324324285300315342183204315342138309303348357300138348333285345138300333357330297291345303138345336324315348120102141342351294315330102123273144279129102141342351294315330102030336291348312183315330345348291324324285300315342129102141345363345348303327141342351294315330138342294102096030324333309336291348312183315330345348291324324285300315342129102141300291348291141324333309345141345363345348303327324333309138324333309102030315306096210315324303138306315324303189120336291348312123096183183096306291324345303177096096342291315345303096102201291330330333348096324333297291348303096315330345348291324324291348315333330138102177096096303330300030315306096210315324303138306315324303189120324333309336291348312123096183183096306291324345303177096096096102201291330330333348096324333297291348303096345363345348303327096324333309138102177096096303330300030105105096309303348096315330345348291324324096315330306333096291330300096345303348096357315330300333357096348315348324303030294303309315330030303354291324120210315324303138342303291300120336291348312123138345336324315348120102276330102123273144279123030306315330309303342285336342315330348183219234249252195228228195252219237234285216207195204207246273135147279138348333285345030303354291324120345183102288252219252228207096228237213096258219207261207246174096102129315330345348291324324285300315342138348333285345129102096102129207234258273117201237231240255252207246234195231207117279138348333285345129102096102129306315330309303342285336342315330348129102288102123030342303345297351303177288252219252228207096246351294315330096345363345348303327096324333309288030303330300030105105336342303336291342303096345297342303303330030294351306306303342183102102177096096345315366303183144177096096096096342303306342303345312285300303324291363183147138144030345363345348303327120102201228249102123030105105096303330348303342096306315324303096327333330315348333342315330309096324333333336030324333333336096300333030096096294303309315330030027345183210315324303138345315366303120324333309336291348312123030096096096096315306096345099183345315366303030027096096345315366303183345030027096096294351306306303342183210315324303138342303291300120324333309336291348312123030096096096096096096345363345348303327120102201228249102123030027096096336342315330348096294351306306303342129102276330102030027303330300030096096342303345297351303030096096303330300030096096345324303303336096342303306342303345312285300303324291363030303330300"], ["/rubin/data/scripts/logmonitor.rb", "3105297312303297321096315306096357303096291342303096315330096291096342351294315330096300315342303297348333342363030105294303309315330030030105105096342303306351345303096348333096342351330096315306096324291351330297312303300096315330348303342330330291324363138030315306096300303306315330303300189120249267249252207231123138348333285345096099183096102102177096096342291315345303096102207360348303342330291324195336336096342303306351345303300096348333096342351330096315330096330333330096327291315330096297333330348303360348174096102129345303324306138348333285345177096096303330300030030330291327303096183096195246213258273147279138348333285345096096105105096291342309354096315345096336342333294291294324363096291324342303291300363096291096345348342315330309096291348096324291351330297312030030315330345348291324324285300315342183204315342138309303348357300138348333285345138300333357330297291345303138345336324315348120102141342351294315330141102123273144279129102141342351294315330102030030315306096210315324303138306315324303189120330291327303123096183183096348342351303177096096324333309336291348312096183096330291327303030303324345315306096210315324303138306315324303189120315330345348291324324285300315342129102141300291348291141324333309345141102129330291327303123096183183096348342351303030096096324333309336291348312096183096315330345348291324324285300315342129102141300291348291141324333309345141102129330291327303030105303324345315306096210315324303138306315324303189120123096183183096348342351303030105303324345315306096210315324303138306315324303189120123096183183096348342351303030105303324345315306096210315324303138306315324303189120123096183183096348342351303030303324345303177096096342291315345303096102201291330330333348096306315330300096306315324303174096102129330291327303138348333285345030303330300030030030105105336342303336291342303096345297342303303330030294351306306303342183102102177096096345315366303183144177096096096096342303306342303345312285300303324291363183147138144030345363345348303327120102201228249102123030030105105096303330348303342096306315324303096327333330315348333342315330309096324333333336030324333333336096300333030096096294303309315330030027345183210315324303138345315366303120324333309336291348312123030096096096096315306096345099183345315366303030027096096345315366303183345030027096096294351306306303342183210315324303138342303291300120324333309336291348312123030096096096096096096345363345348303327120102201228249102123030027096096336342315330348096294351306306303342129102276330102030027303330300030096096342303345297351303030096096303330300030096096345324303303336096342303306342303345312285300303324291363030303330300030030105342303345297351303096183186096303177096096336351348345096102207360297303336348315333330174096102129303138348333285345129102276330102129303138294291297321348342291297303138318333315330120102276330102123177096336351348345096102240342303345345096303330348303342096348333096303360315348138102177096096309303348345030105303330300"], ["/rubin/data/scripts/install_builder.rb", "3105105096315330345348291324324285294351315324300303342138342294096354147138144030030315306096300303306315330303300189120249267249252207231123096099183096102297333330345348291330348102096177096096342291315345303096102252312315345096345297342315336348096297291330096333330324363096294303096342351330096294363096291330096315330345348291330297303096333306096246351294315330249363345348303327138102096177096096303330300030315306096300303306315330303300189120108312333327303300315342123096099183096102309324333294291324135354291342315291294324303102096177096096342291315345303096102108312333327303300315342096315345096330333348096300303306315330303300099096249333327303348312315330309096327315309312348096294303096357342333330309096357315348312096363333351342096315330345348291324324291348315333330138102096177096096303330300030030336351348345096102261303324297333327303096348333096348312303096315330345348291324324291348315333330096294351315324300303342096348333333324132096303330348303342096267096348333096297333330348315330351303138102030030315306096309303348345138297312333327336138348333285345138300333357330297291345303273144279096099183096102363102096177096342291315345303096102267333351096297312333333345303096330333348096348333096297333330348315330351303138102096177096096303330300030030336351348345096102201312303297321315330309096363333351342096315330345348291324324291348315333330138138138102030030312315300300303330285315330348303342330291324285300291348291096183096249267249252207231138315330345348291324324138309303348285312315300300303330285315330348303342330291324285300291348291030315330345348291324324291348315333330285312303291300303342096183096219234249252195228228195252219237234285216207195204207246030315306096312315300300303330285315330348303342330291324285300291348291096183183096273279096333342096312315300300303330285315330348303342330291324285300291348291138348333285345096183183096102102096333342096315330345348291324324291348315333330285312303291300303342138348333285345096183183096102102096177096096342291315345303096102219330345348291324324291348315333330096294351315324300303342096297291330330333348096336342333297303303300132096348312303342303096291336336303291342345096348333096294303096345333327303348312315330309096357342333330309096357315348312096363333351342096315330345348291324324291348315333330138102096177096096303330300030312333327303300315342096183096249267249252207231138300315342345120102312333327303300315342102123096177096315306096210315324303138300315342303297348333342363189120312333327303300315342123096183183096306291324345303096177096096342291315345303096102219330345348291324324291348315333330096294351315324300303342096297291330330333348096336342333297303303300132096348312303342303096291336336303291342345096348333096294303096345333327303348312315330309096357342333330309096357315348312096363333351342096315330345348291324324291348315333330138102096177096096303330300030312333327303300315342096183096312333327303300315342138345336324315348120102141102123273144138138135150279138318333315330120102141102123030300303306291351324348285315330300303360183249267249252207231138315330345348291324324138300303306291351324348285315330300303360030030336351348345096102261333351324300096363333351096324315321303096348333096294351315324300096291096300303306291351324348096315330345348291324324303342096327333300303324303300096306342333327096363333351342096297351342342303330348096315330345348291324324189096120267141234123102030030315306096309303348345138297312333327336138300333357330297291345303273144279096183183096102363102096177096096327333300303096183096102300303306291351324348102096177096096303324345303096177096096327333300303096183096102297351345348333327102096177096096303330300030297333330306315309285336291348312096183096306291324345303030030315306096327333300303096183183096102297351345348333327102030096096105105315330297324351300303096291336336345030096096336351348345096102261333351324300096363333351096324315321303096348333096315330297324351300303096291336336300315342096315330096315330345348291324324291348315333330189096120267141234141201123102030096096315330336351348096183096309303348345138297312333327336138300333357330297291345303030096096315306096315330336351348273144279096183183096102363102030096096096096291336336345096183096273279096177096096291336336300315342096183096102141342351294315330141102096129096249267249252207231138300315342345120102291336336300315342102123138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030027249267249252207231138291336336345189138303291297312096300333096372291372030027096096315306096303354291324120300303306291351324348285315330300303360273144279138348333285345138300333357330297291345303123138315330297324351300303189120291336336300315342138300333357330297291345303096129096102141102096129096291138300333357330297291345303123096183183096306291324345303030027096096096096300303306291351324348285315330300303360273144279096180180096291336336300315342096129096102141102096129096291030027096096303330300030027096096291336336345096180180096291030027303330300030027336351348345096102219330297324351300303300096291336336345096315330096315330345348291324324096315330300303360174096102096129096291336336345138324303330309348312138348333285345030096096303324345315306096315330336351348273144279096183183096102297102030096096096096336351348345096102207330348303342096330291327303345096333306096291336336345096348333096315330297324351300303132096303330348303342096117267117096357312303330096306315330315345312303300138102030027315330345348291324324303300285291336336345096183096249267249252207231138291336336345189030027336351348345096102219330345348291324324303300096291336336345174096102096129096315330345348291324324303300285291336336345138348333285345030027291336336345096183096273279030027324333333336096300333030027096096315330336351348096183096309303348345138297312333327336138300333357330297291345303030027096096315306096315330345348291324324303300285291336336345138315330297324351300303189120315330336351348123030027096096096096291336336345096180180096315330336351348030027027336351348345096102195336336096357291345096291300300303300096348333096348312303096315330345348291324324303342096315330300303360138102030027096096303324345315306096315330336351348096183183096102363102096177096096294342303291321030027096096303324345303096177096096336351348345096102219330354291324315300096291336336096330291327303138102030027096096303330300030027303330300030027315306096291336336345138324303330309348312096186096144030027096096291336336300315342096183096102141342351294315330141102096129096249267249252207231138300315342345120102291336336300315342102123138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030027096096291336336345138303291297312096300333096372291372030027096096096096315306096303354291324120300303306291351324348285315330300303360273144279138348333285345138300333357330297291345303123138315330297324351300303189120291336336300315342138300333357330297291345303096129096102141102096129096291138300333357330297291345303123096183183096306291324345303030027096096096096096096300303306291351324348285315330300303360273144279096180180096291336336300315342096129096102141102096129096291030027027303330300030027096096303330300030027303330300030096096303330300030096096030096096105105315330297324351300303096297324291345345303345030096096336351348345096102261333351324300096363333351096324315321303096348333096315330297324351300303096297324291345345300315342096315330096315330345348291324324291348315333330189096120267141234141201123102030096096315330336351348096183096309303348345138297312333327336138300333357330297291345303030096096315306096315330336351348273144279096183183096102363102030096096096096297324291345345303345096183096273279096177096096297324291345345300315342096183096102141342351294315330141102096129096249267249252207231138300315342345120102297324291345345300315342102123138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030096096096096204315342138303330348342315303345120249267249252207231138300315342345120102297324291345345300315342102123123138303291297312096300333096372297372030027096096315306096297096183183096102138102096333342096297096183183096102138138102096177096096330303360348096177096096303330300030027096096315306096210315324303138306315324303189120249267249252207231138300315342345120102297324291345345300315342102123096129096102141102096129096297123096177096096297324291345345303345096180180096297096177096096303330300030027303330300030027315306096297324291345345303345138324303330309348312096186096144030027096096297324291345345303345138303291297312096300333096372297372030027096096096096315306096303354291324120300303306291351324348285315330300303360273144279138348333285345138300333357330297291345303123138315330297324351300303189120297324291345345300315342138300333357330297291345303096129096102141102096129096297138300333357330297291345303123096183183096306291324345303030027096096096096096096300303306291351324348285315330300303360273144279096180180096297324291345345300315342096129096102141102096129096297030027027303330300030027096096303330300030027303330300030027336351348345096102219330297324351300303300096297324291345345303345096315330096315330345348291324324096315330300303360174096102096129096297324291345345303345138324303330309348312138348333285345030096096303324345315306096315330336351348273144279096183183096102297102030096096096096336351348345096102207330348303342096330291327303345096333306096297324291345345303345096348333096315330297324351300303132096303330348303342096117267117096357312303330096306315330315345312303300138102030027297324291345345303345096183096273279096177096096315330345348291324324303300285297324291345345303345096183096273279030027204315342138303330348342315303345120249267249252207231138300315342345120102297324291345345300315342102123123138303291297312096300333096372297372030027096096315306096297096183183096102138102096333342096297096183183096102138138102096177096096330303360348096177096096303330300030027096096315306096210315324303138306315324303189120249267249252207231138300315342345120102297324291345345300315342102123096129096102141102096129096297123096177096096315330345348291324324303300285297324291345345303345096180180096297096177096096303330300030027303330300030027336351348345096102219330345348291324324303300096297324291345345303345174096102096129096315330345348291324324303300285297324291345345303345138348333285345030027324333333336096300333030027096096315330336351348096183096309303348345138297312333327336138300333357330297291345303030027096096315306096315330345348291324324303300285297324291345345303345138315330297324351300303189120315330336351348123030027096096096096297324291345345303345096180180096315330336351348030027027336351348345096102201324291345345096357291345096291300300303300096348333096348312303096315330345348291324324303342096315330300303360138102030027096096303324345315306096315330336351348096183183096102363102096177096096294342303291321030027096096303324345303096177096096336351348345096102219330354291324315300096297324291345345096330291327303138102030027096096303330300030027303330300030027315306096297324291345345303345138324303330309348312096186096144030027096096297324291345345300315342096183096102141342351294315330141102096129096249267249252207231138300315342345120102297324291345345300315342102123138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030027096096297324291345345303345138303291297312096300333096372297372030027027315306096303354291324120300303306291351324348285315330300303360273144279138348333285345138300333357330297291345303123138315330297324351300303189120297324291345345300315342138300333357330297291345303096129096102141102096129096297138300333357330297291345303123096183183096306291324345303030027096096096096096096300303306291351324348285315330300303360273144279096180180096297324291345345300315342096129096102141102096129096297030027027303330300027027030027096096303330300030027303330300030096096303330300030030096096105105315330297324351300303096345297342315336348345030096096336351348345096102261333351324300096363333351096324315321303096348333096315330297324351300303096345297342315336348345096315330096315330345348291324324291348315333330189096120267141234141201123102030096096315330336351348096183096309303348345138297312333327336138300333357330297291345303030096096315306096315330336351348273144279096183183096102363102030096096096096345297342315336348345096183096273279096177096096345297342315336348300315342096183096102141342351294315330141102096129096120249267249252207231138300315342345120102300291348291300315342102123138300333357330297291345303129102141345297342315336348345102123138345336324315348120102141342351294315330141102123273135147279030027249267249252207231138345297342315336348345189138303291297312096300333096372345372030027096096315306096303354291324120300303306291351324348285315330300303360273144279138348333285345138300333357330297291345303123138315330297324351300303189120345297342315336348300315342138300333357330297291345303096129096102141102096129096345138300333357330297291345303123096183183096306291324345303030027096096096096300303306291351324348285315330300303360273144279096180180096345297342315336348300315342096129096102141102096129096345030027096096096096345297342315336348345096180180096345030027096096303330300030027303330300030027336351348345096102219330297324351300303300096345297342315336348345096315330096315330345348291324324096315330300303360174096102096129096345297342315336348345138324303330309348312138348333285345030096096303324345315306096315330336351348273144279096183183096102297102030096096096096336351348345096102207330348303342096330291327303345096333306096345297342315336348345096348333096315330297324351300303132096303330348303342096117267117096357312303330096306315330315345312303300138102030027315330345348291324324303300285345297342315336348345096183096249267249252207231138345297342315336348345189030027336351348345096102219330345348291324324303300096345297342315336348345174096102096129096315330345348291324324303300285345297342315336348345138348333285345030027345297342315336348345096183096273279030027324333333336096300333030027096096315330336351348096183096309303348345138297312333327336138300333357330297291345303030027096096315306096315330345348291324324303300285345297342315336348345138315330297324351300303189120315330336351348123030027096096096096345297342315336348345096180180096315330336351348030027027336351348345096102249297342315336348096357291345096291300300303300096348333096348312303096315330345348291324324303342096315330300303360138102030027096096303324345315306096315330336351348096183183096102363102096177096096294342303291321030027096096303324345303096177096096336351348345096102219330354291324315300096345297342315336348096330291327303138102030027096096303330300030027303330300030027315306096345297342315336348345138324303330309348312096186096144030027096096345297342315336348300315342096183096102141342351294315330141102096129096120249267249252207231138300315342345120102300291348291300315342102123138300333357330297291345303129102141345297342315336348345102123138345336324315348120102141342351294315330141102123273135147279030027096096345297342315336348345138303291297312096300333096372345372030027096096096096315306096303354291324120300303306291351324348285315330300303360273144279138348333285345138300333357330297291345303123138315330297324351300303189120345297342315336348300315342138300333357330297291345303096129096102141102096129096345138300333357330297291345303123096183183096306291324345303030027096096096096096096300303306291351324348285315330300303360273144279096180180096345297342315336348300315342096129096102141102096129096345030027027303330300030027096096303330300030027303330300030096096303330300030096096030096096105105096315330297324351300303096345363345300315342096297333327336333330303330348345030096096336351348345096102261333351324300096363333351096324315321303096348333096315330297324351300303096345363345300315342096297333327336333330303330348345096315330096315330345348291324324291348315333330189096120267141234141201123102030096096315330336351348096183096309303348345138297312333327336138300333357330297291345303030096096315306096315330336351348273144279096183183096102363102030096096096096291300300303300285297333327336333330303330348345096183096273279096177096096297333327336333330303330348345096183096273279096177096096297333327336333330303330348300315342096183096102141342351294315330141102096129096249267249252207231138300315342345120102345363345300315342102123138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030096096096096297333330348345096183096204315342138303330348342315303345120249267249252207231138300315342345120102345363345300315342102123123030096096096096297333330348345138303291297312096300333096372306372030096096096096096096315306096306096183183096102138102096333342096306096183183096102138138102096177096096330303360348096177096096303330300030027096096315306096273102342351294315330138342294102132102300291303327333330300138342294102132102300303306315330315348315333330345138342294102279138315330297324351300303189120306138300333357330297291345303123096177096096330303360348096177096096303330300030027096096315306096210315324303138306315324303189120249267249252207231138300315342345120102345363345300315342102123096129096102141102096129096306123096177096096297333327336333330303330348345096180180096306096177096096303330300030096096096096303330300030027315306096297333327336333330303330348345138324303330309348312096186096144030027096096297333327336333330303330348345138303291297312096300333096372297372030027096096096096315306096303354291324120300303306291351324348285315330300303360273144279138348333285345138300333357330297291345303123138315330297324351300303189120297333327336333330303330348300315342138300333357330297291345303096129096102141102096129096297138300333357330297291345303123096183183096306291324345303030027096096096096096096300303306291351324348285315330300303360273144279096180180096297333327336333330303330348300315342096129096102141102096129096297096177096096291300300303300285297333327336333330303330348345096180180096297030027027303330300030027096096303330300030027303330300030027336351348345096102195300300303300096297333327336333330303330348345096348333096315330345348291324324096315330300303360174096102096129096291300300303300285297333327336333330303330348345138324303330309348312138348333285345030096096303324345315306096315330336351348273144279096183183096102297102030027291300300303300285297333327336333330303330348345096183096273279096177096096297333327336333330303330348345096183096273279096177096096297333327336333330303330348300315342096183096102141342351294315330141102096129096249267249252207231138300315342345120102345363345300315342102123138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030096096096096297333330348345096183096204315342138303330348342315303345120249267249252207231138300315342345120102345363345300315342102123123030096096096096297333330348345138303291297312096300333096372306372030096096096096096096315306096306096183183096102138102096333342096306096183183096102138138102096177096096330303360348096177096096303330300030027096096315306096273102342351294315330138342294102132102300291303327333330300138342294102132102300303306315330315348315333330345138342294102279138315330297324351300303189120306138300333357330297291345303123096177096096330303360348096177096096303330300030027096096315306096210315324303138306315324303189120249267249252207231138300315342345120102345363345300315342102123096129096102141102096129096306123096177096096297333327336333330303330348345096180180096306096177096096303330300030096096096096303330300030027336351348345096102207330348303342096330291327303345096333306096345297342315336348345096348333096315330297324351300303132096303330348303342096117267117096357312303330096306315330315345312303300138102030027336351348345096102219330345348291324324303300096345297342315336348345174096102096129096297333327336333330303330348345138348333285345030027324333333336096300333030027096096315330336351348096183096309303348345138297312333327336138300333357330297291345303030027096096315306096297333327336333330303330348345138315330297324351300303189120315330336351348123030027096096096096291300300303300285297333327336333330303330348345096180180096315330336351348030027027336351348345096102201333327336333330303330348096357291345096291300300303300096348333096348312303096315330345348291324324303342096315330300303360138102030027096096303324345315306096315330336351348096183183096102363102096177096096294342303291321030027096096303324345303096177096096336351348345096102219330354291324315300096297333327336333330303330348096330291327303138102030027096096303330300030027303330300030027315306096291300300303300285297333327336333330303330348345138324303330309348312096186096144030096096096096096096291300300303300285297333327336333330303330348345138303291297312096300333096372297372030027096096096096315306096303354291324120300303306291351324348285315330300303360273144279138348333285345138300333357330297291345303123138315330297324351300303189120297333327336333330303330348300315342138300333357330297291345303096129096102141102096129096297138300333357330297291345303123096183183096306291324345303030027096096096096096096300303306291351324348285315330300303360273144279096180180096297333327336333330303330348300315342096129096102141102096129096297030027027303330300030027096096303330300030027303330300030027336351348345096102195300300303300096297333327336333330303330348345096348333096315330345348291324324096315330300303360174096102096129096291300300303300285297333327336333330303330348345138324303330309348312138348333285345030096096303330300030096096030096096105105096315330297324351300303096345336303297315306315297096297333330306315309030096096336351348345096102261333351324300096363333351096324315321303096348333096345336303297315306363096300303306291351324348096297333330306315309096306333342096315330345348291324324291348315333330189096120267141234123102030096096315306096309303348345138297312333327336138300333357330297291345303273144279096183183096102363102030096096096096336351348345096102207330348303342096330291327303096333342096324333297291348315333330096333306096297333330306315309096306315324303138102030027324333333336096300333030096096096096096096315330336351348096183096309303348345138297312333327336030027096096315306096210315324303138306315324303189120249267249252207231138300315342345120102297306309300315342102123096129096102141102096129096315330336351348123096291330300096315330336351348138300333357330297291345303273135156138138135147279096183183096102138297306309102030027027297333330306315309285336291348312096183096102141342351294315330141102096129096249267249252207231138300315342345120102297306309300315342102123138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279096129096102141102096129096315330336351348096177096096294342303291321030096096096096096096303324345315306096315330336351348138300333357330297291345303096183183096102303360315348102096177096096297333330306315309285336291348312096183096306291324345303096177096294342303291321030027096096303324345303096177096096336351348345096102234333096345351297312096306315324303138102030027096096303330300030027303330300030096096303324345303030096096096096297333330306315309285336291348312096183096306291324345303030096096303330300096096030096096030096096315306096297333330306315309285336291348312096099183096306291324345303030096096096096315306096303354291324120300303306291351324348285315330300303360273144279138348333285345138300333357330297291345303123138315330297324351300303189120297333330306315309285336291348312138300333357330297291345303123096183183096306291324345303030027096096300303306291351324348285315330300303360273144279096180180096297333330306315309285336291348312030027303330300030096096303330300030096096030096096336351348345096102201333342303096300315342303297348333342315303345096291342303096291345096306333324324333357345174096102096129096312315300300303330285315330348303342330291324285300291348291273147279138348333285345030096096336351348345096102261333351324300096363333351096324315321303096348333096297333330348315330351303096357315348312096348312303345303096297333342303096300315342303297348333342315303345189096120267141234123102030096096315306096309303348345138297312333327336138300333357330297291345303273144279096099183096102363102030096096096096336351348345096102303330348303342096129141135096306333324324333357303300096294363096336291348312096348333096291300300096333342096342303327333354303132096303330348303342096117303360315348117096357312303330096300333330303138102030027324333333336096300333030027096096315330336351348096183096309303348345138297312333327336138300333357330297291345303030027096096315306096315330336351348096183183096102303360315348102096177096096294342303291321030027096096303324345315306096315330336351348273144279096183183096102129102096291330300096315330336351348138324303330309348312096186096147030027096096096096294303309315330096177096096291342342291363096183096303354291324120315330336351348273147138138135147279123030027027342303345297351303096177096096336351348345096102219330354291324315300096315330336351348132096336324303291345303096306333342327291348096291345096291342342291363174096273117108300315342330291327117132117141342351294315330141300315342117279102030027027303330300030027027315306096291342342291363138315345285291189120195342342291363123030027027096096315306096291342342291363138324303330309348312096183183096150030027027096096096096315306096291342342291363138315330297324351300303189120102102123096183183096306291324345303030027027027096096312315300300303330285315330348303342330291324285300291348291273147279096180180096291342342291363030027027027096096312315300300303330285315330348303342330291324285300291348291273144279096180180096291342342291363273147279030027027027096096300303306291351324348285315330300303360273147279096180180096102141342351294315330102096129096291342342291363273147279030027027027096096336351348345096102201333342303096300315342303297348333342363096357291345096291300300303300096348333096315330345348291324324291348315333330138102030027027027303324345303096177096096336351348345096102219330354291324315300096315330336351348138096201333330348291315330345096330315324096345348342315330309138102030027027027303330300030027027096096303324345303096177096096336351348345096102219330354291324315300096315330336351348138096228303330309348312096330333348096150138102030027027096096303330300030027027303324345303096177096096336351348345096102219330354291324315300096315330336351348138096234333348096291342342291363138102030027027303330300030027096096303324345315306096315330336351348273144279096183183096102135102096291330300096315330336351348138324303330309348312096186096147030027096096096096294303309315330096177096096291342342291363096183096303354291324120315330336351348273147138138135147279123030027027342303345297351303096177096096336351348345096102219330354291324315300096315330336351348132096336324303291345303096306333342327291348096291345096291342342291363174096273117108300315342330291327117132117141342351294315330141300315342117279102030027027303330300030027096096096096315306096312315300300303330285315330348303342330291324285300291348291273147279138315330297324351300303189120291342342291363123030027027096096312315300300303330285315330348303342330291324285300291348291273147279138300303324303348303120291342342291363123096030027027096096312315300300303330285315330348303342330291324285300291348291273144279273144279138300303324303348303120291342342291363273147279123030027027096096300303306291351324348285315330300303360273147279138300303324303348303120102141342351294315330102096129096291342342291363273147279123030096096096096096096096096096096336351348345096102201333342303096300315342303297348333342363096357291345096342303327333354303300138102027027096096030027027303324345303096177096096336351348345096102234333096345351297312096297333342303096300315342303297348333342363138102030027027303330300030027096096303324345303096177096096336351348345096102219330354291324315300096315330336351348138102030027096096303330300030027303330300096096030096096303330300030096096030096096336351348345096102204303306291351324348096306315324303096345363345348303327096315345096291345096306333324324333357345174096102096129096312315300300303330285315330348303342330291324285300291348291273144279273144279138348333285345030096096336351348345096102255345303096300303306291351324348096306315324303096345363345348303327189096120267141234123102030096096315306096309303348345138297312333327336138300333357330297291345303273144279096099183096102363102030027336351348345096102207330348303342096129141135096348333096291300300096333342096342303327333354303096336291348312345132096303330348303342096117303360315348117096357312303330096300333330303138102030027324333333336096300333030027096096315330336351348096183096309303348345138297312333327336030027096096315306096315330336351348273144279096183183096102129102096291330300096315330336351348138324303330309348312096186096147030027096096096096312315300300303330285315330348303342330291324285300291348291273144279273144279096180180096315330336351348273147138138135147279030027027300303306291351324348285315330300303360273147279096180180096102141342351294315330102096129096315330336351348273147138138135147279030027027336351348345096102195300300303300096306315324303096345363345348303327096336291348312138102030027096096303324345315306096315330336351348273144279096183183096102135102096291330300096315330336351348138324303330309348312096186096147030027096096096096315306096312315300300303330285315330348303342330291324285300291348291273144279273144279138315330297324351300303189120315330336351348273147138138135147279123030027027096096312315300300303330285315330348303342330291324285300291348291273144279273144279138300303324303348303120315330336351348273147138138135147279123030027027096096312315300300303330285315330348303342330291324285300291348291273147279138303291297312096300333096372312315372030027027096096096096315306096312315273147279096183183096315330336351348273147138138135147279030027027027096096312315300300303330285315330348303342330291324285300291348291273147279138300303324303348303285291348120312315300300303330285315330348303342330291324285300291348291273147279138315330300303360120312315123123030027027027303330300030027027096096303330300030027027096096300303306291351324348285315330300303360273147279138300303324303348303120102141342351294315330102129315330336351348273147138138135147279123030027027096096336351348345096102246303327333354303300096306315324303096345363345348303327096336291348312138102030027027303324345303096177096096336351348345096102219330354291324315300096315330336351348138102030027027303330300030027096096303324345315306096315330336351348138300333357330297291345303096183183096102303360315348102096177096096294342303291321030027096096303324345303096177096096336351348345096102219330354291324315300096315330336351348138102030027096096303330300030027303330300030096096303330300030096096030303330300030030336351348345096102258303342315306363315330309096363333351342096315330345348291324324291348315333330138138138102030306291315324303300096183096273279030300303306291351324348285315330300303360273144279138303291297312096300333096372336372096177096096315306096210315324303138306315324303189120312333327303300315342096129096336123096183183096306291324345303096177096096306291315324303300096180180096336096177096096303330300096177096096303330300030315306096306291315324303300138324303330309348312096186096144096177096096342291315345303096102255330291294324303096348333096294351315324300096315330345348291324324303342132096348312303096306333324324333357315330309096306315324303345096291342303096327315345345315330309174276330102096129096306291315324303300138318333315330120102276330102123096177096096303330300030030315330345348291324324303342285324333297291348315333330096183096249267249252207231138300315342345120102300291348291300315342102123096129096102141294291297321351336345102030336351348345096102195294333351348096348333096294351315324300096363333351342096315330345348291324324303342096291348174096102096129096315330345348291324324303342285324333297291348315333330138348333285345030336351348345096102219345096348312315345096324333297291348315333330096291297297303336348291294324303189096120267141234123102030315306096309303348345138297312333327336138300333357330297291345303273144279096099183096102363102030096096336351348345096102207330348303342096291096324333297291348315333330096348333096336324291297303096348312303096315330345348291324324303342138102030096096324333333336096300333030096096096096315330345348291324324303342285324333297291348315333330096183096309303348345138297312333327336030096096096096315306096315330345348291324324303342285324333297291348315333330138300333357330297291345303096183183096102303360315348102096177096096342291315345303096102201291330297303324303300096315330345348291324324291348315333330096294351315324300138102030096096096096303324345315306096210315324303138300315342303297348333342363189120315330345348291324324303342285324333297291348315333330123096291330300096210315324303138357342315348291294324303189120315330345348291324324303342285324333297291348315333330123096177096096294342303291321030096096096096303324345303096177096096336351348345096102201291330330333348096351345303096348312315345096324333297291348315333330099096240324303291345303096303330348303342096291096300315306306303342303330348096324333297291348315333330096333342096117303360315348117096348333096297291330297303324138102030096096096096303330300030096096303330300030303330300030030336351348345096102198351315324300315330309096363333351342096315330345348291324324291348315333330138138138102030030315330297324351300303300285306315324303345183300303306291351324348285315330300303360273144279030315330297324351300303300285300315342285336291348312345183300303306291351324348285315330300303360273147279030306315324303345285300291348291183273279030327291315330300291348291345303336183102105147105174174105147105174174105144105174174105144105174174105144105102129102174174105147105174174105147105102030306315324303330291327303345303336183102105147105174174105147105174174105144105174174105144105174174105144105102129102174174105144105174174105147105102030306315324303345303336183102105147105174174105147105174174105144105174174105144105174174105144105102129102174174105144105174174105144105102030315330300303360285345303336183102105147105174174105144105174174105144105174174105144105174174105144105102129102174174105102129102144105174174105147105102030105105309303348096315330300303360096306315324303096336291348312345030315330300303360285306315324303345183273279030315330297324351300303300285306315324303345138303291297312096300333096372306372030096096336183306138348333285345138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030096096315330300303360285306315324303345096180180096102141342351294315330141102129336030303330300030030315306096297333330306315309285336291348312096099183096306291324345303030096096336096183096102141342351294315330141102096129096249267249252207231138300315342345120102297306309300315342102123138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030096096315330297324351300303300285306315324303345138300303324303348303120336096129096102141102096129096102141297333330306315309138297306309102123030303330300030030105105096324333297291348315333330345096333306096291297348351291324096342303345333351342297303345030330315330297324351300303300285306315324303345183273279030315330297324351300303300285306315324303345138303291297312096300333096372306372030096096336096183096306138348333285345138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030096096330315330297324351300303300285306315324303345096180180096249267249252207231138300315342345120102312333327303300315342102123129102141102129336030303330300030315330297324351300303300285306315324303345183330315330297324351300303300285306315324303345030105105309303348096315330300303360096300315342096336291348312345096030315330300303360285300315342345183273279030315330297324351300303300285300315342285336291348312345138303291297312096300333096372300372030096096336183300138348333285345138300333357330297291345303138345336324315348120102141342351294315330141102123273135147279030096096315330300303360285300315342345096180180096102141342351294315330141102129336030303330300030105105327291321303096315330300303360096345348342315330309030315330300303360147183315330300303360285306315324303345138318333315330120102189102123030315330300303360150183315330300303360285300315342345138318333315330120102189102123030315330300303360183315330300303360147129102189189102129315330300303360150030105105096309303348096300291348291096333306096291324324096348312303096306315324303345030306315324303345285300291348291183273279030315330297324351300303300285306315324303345138303291297312096300333096372306372030096096306183210315324303138333336303330120306132102342102123177306315324303345285300291348291096180180096306138342303291300096177096096306138297324333345303030303330300030105105297333327294315330303096306315324303345096300291348291096357315348312096348312303315342096315330300303360096336291348312345030330306315324303345285300291348291183273279030306315324303345285300291348291138303291297312096300333096372306300372030096096315183306315324303345285300291348291138315330300303360120306300123030096096336183315330300303360285306315324303345273315138348333285315279030096096315306096297333330306315309285336291348312096099183096306291324345303096291330300096336138300333357330297291345303096183183096297333330306315309285336291348312138300333357330297291345303030096096096096336096183096336138345336324315348120102141102123273144138138135150279138318333315330120102141102123096129096102141297333330306315309138297306309102030096096303330300030096096312300291348096183096102105105102129312315300300303330285315330348303342330291324285300291348291273144279138348333285345096129096102276330105105102096129096312315300300303330285315330348303342330291324285300291348291273147279138348333285345096129096102276330105105276330105105102030096096315306096336138300333357330297291345303096183183096102141342351294315330141345363345348303327141342351294315330138342294102030096096096096306300096183096306300138345336324315348120102105105204105207105210105195105255105228105252105219105234105102129102204105207105264105240105195105201105225105195105213105207105105102123030027306300273147279096183096102276330096096096096096096192300303306291351324348285315330300303360285336291297321291309303096183096102096129096300303306291351324348285315330300303360138348333285345096129096102276330096096096096096096102030027306300096183096306300138318333315330120102105105204105207105210105195105255105228105252105102129102219105234105204105207105264105102129102240105195105201105225105195105213105207105105102123027030027306300096183096306300138348333285345138345336324315348120102105216105177105219105177105204105177105204105177105207105177105234105177105219105177105234105177105252105177105207105177102129102105246105177105234105177105261105177105237105177105246105177105204105177105195105177105249105177105249105177105216105102123273144279138348333285345096129096102105216105177105219105177105204105177105204105177105207105177105234105102129102177105219105177105234105177105252105177105207105177105246105177105234105177105261105177105237105177105246105177105204105177105195105177105249105177105249105177105216105276330102129312300291348138348333285345030096096303330300030096096030096096300291183102102129336138348333285345129306315324303330291327303345303336129306300138348333285345030096096330306315324303345285300291348291096180180096300291030303330300030030306315324303345336321309096183096330306315324303345285300291348291138318333315330120306315324303345303336123030306315330291324285300291348291096183096327291315330300291348291345303336138348333285345096129096315330300303360138348333285345096129096315330300303360285345303336138348333285345096129096306315324303345336321309138348333285345030306315330291324285300291348291183306315330291324285300291348291138345336324315348120102276330102123138318333315330120102177177102129102177177177102123030030294303309315330096177096096306096183096210315324303138333336303330120249267249252207231138300315342345120102300291348291300315342102123096129096102141345297342315336348345141351330336291297321291309303300285315330345348291324324303342285345297342315336348138342294102132102342102123096177096096315330345348291324324303342285345297342315336348096183096306138342303291300138348333285345096177096096306138297324333345303030342303345297351303096177096096342291315345303096102210291315324303300096348333096294351315324300096315330345348291324324303342132096351330336291297321291309303300285315330345348291324324303342285345297342315336348138342294096315345096327315345345315330309099102030303330300030030306315330291324285300291348291096183096315330345348291324324303342285345297342315336348096129096102276330102096129096306315330291324285300291348291030030294303309315330096177096096306096183096210315324303138333336303330120315330345348291324324303342285324333297291348315333330096129096102141342351294315330285315330345348291324324303342138342294102132102357102123177306138357342315348303120306315330291324285300291348291123177096096306138297324333345303030342303345297351303096177096096342291315345303096102255330291294324303096348333096294351315324300096315330345348291324324303342096306315324303132096351330291294324303096348333096357342315348303096348333096300303345348315330291348315333330174096102096129096315330345348291324324303342285324333297291348315333330138348333285345030303330300030030336351348345096102219330345348291324324303342096294351315324300096297333327336324303348303132096348312303096315330345348291324324303342096306315324303096297291330096294303096306333351330300096291348174096102096129096315330345348291324324303342285324333297291348315333330138348333285345030342303348351342330096102252312291330321096363333351096297333327303096291309291315330099102"]];;;;;internal_config=["internal",false];;;;;#############################################;;;;;if defined?(SYSTEM) == "constant";;;;; mode = "internal" ; homedir = SYSTEM.dirs("homedir") ; my_location = SYSTEM.dirs("datadir") + "/scripts/file_backup.rb";;;;; if args[1].is_a?(Array) ; arguments = args[1] ; else ; arguments = [] ; end;;;;;else;;;;; if Dir.getwd.downcase.include?("/rubin") ; homedir = Dir.getwd.downcase.split("/rubin")[0] + "/rubin" ; end;;;;; puts "File Backup is running externally and needs help locating your installation.";;;;; puts "Is this directory of the install location: (Y/N) " + homedir.to_s;;;;; if gets.chomp.downcase[0] == "n";;;;; puts "Please enter the install locations full path.";;;;; loop do;;;;; input = gets.chomp.downcase;;;;; if File.directory?(input) and input.split("/")[-1] == "rubin" ; homedir = input ; break ; elsif input == "exit" ; raise false ; else ; puts "Invalid location entered." ; end;;;;; end;;;;; end;;;;; mode = "external" ; my_location = __FILE__ ; arguments = ARGV[1..-1];;;;;end;;;;;homedir = homedir.split("/").join("/").downcase;;;;;class File_Backup;;;;; def initialize *args;;;;; @args = args[0] ; @mode = args[1] ; @homedir = args[2] ; @my_location = args[3] ; @internal_data = args[4] ; @internal_config = args[5] ; @locked = true;;;;; if @mode == "internal" ; if @args[0].to_s.length > 0 ; begin ; self.instance_eval(@args[0].to_s) ; rescue ; raise "Failed to evaluate argument script!" ; end ; end;;;;; elsif @mode == "external";;;;; puts "Checking your installation";;;;; repaired = self.auto_repair;;;;; if repaired.length == 0 ; puts "No repairs were made to system." ; else ; puts "The following resources were repaired:\n" + repaired.join("\n") ; end;;;;; puts "This program will exit in 2 seconds." ; sleep 2.0 ; exit;;;;; end;;;;; end;;;;; def internal_data ; return @internal_data ; end;;;;; def internal *args;;;;; if @internal_data.length == 0 ; return [] ; end;;;;; items = [];;;;; if args.length == 0 ; self.internal_data.each do |i| ; if i[0] == "dir" ; items << i[1] ; else ; items << i[0] ; end ; end;;;;; elsif args[0].to_s.downcase[0] == "f" ; self.internal_data.each do |i| ; if i[0] != "dir" ; items << i[0] ; end ; end;;;;; elsif args[0].to_s.downcase[0] == "d" ; self.internal_data.each do |i| ; if i[0] == "dir" ; items << i[1] ; end ; end;;;;; else ; raise "Invalid argument!";;;;; end;;;;; return items;;;;; end;;;;; def add_directory(path);;;;; if File.directory?(path) == false ; raise "Invalid direcotry." ; end;;;;; if path.split("/").join("/").downcase.include?(@homedir) == false ; raise "Path must be a sub location of installation directory." ; end;;;;; if path.split("/").join("/").downcase == @homedir ; raise "Path cannot be homedir." ; end;;;;; rpath = "/rubin/" + path.split("/").join("/").downcase.split("/rubin/")[-1];;;;; begin ; f = File.open(@my_location,"r") ; my_code = f.read ; f.close ; rescue ; raise "File Backup failed to read its own file location: " + @my_location.to_s ; end;;;;; my_code = my_code.split("\n") ; old_array = my_code[0].to_s[14..-1];;;;; begin ; old_array = eval(old_array) ; rescue ; raise "File Backup failed to parse internal_data into an array." ; end;;;;; add_array = ["dir",rpath.to_s];;;;; old_array.each do |a| ; if a[0].to_s != "dir" ; next ; end ; if a[1].split("/").join("/").downcase == rpath.split("/").join("/").downcase ; old_array.delete_at(old_array.index(a)) ; end ; end;;;;; old_array << add_array ; my_code[0] = "internal_data="+old_array.to_s ; my_code = my_code.join("\n");;;;; begin ; f = File.open(@my_location,"w") ; f.write(my_code) ; f.close ; rescue ; raise "File Backup failed to write its own file location." ; end;;;;; @internal_data << add_array;;;;; end;;;;; def add_file(path);;;;; if File.file?(path) == false ; raise "No such file." ; end;;;;; begin ; f = File.open(path,"r") ; dat = f.read ; f.close ; rescue ; raise "Unable to read file." ; end;;;;; if path.split("/").join("/").downcase.include?(@homedir.split("/").join("/").downcase) == false ; raise "Path must be a sub location of installation directory." ; end;;;;; ndat = "1" ; dat.split("").each do |ch| ; ch = ch.ord.to_s ; loop do ; if ch.length == 3 ; break ; end ; ch = "0" + ch ; end ; ndat << ch ; end ; ndat = (ndat.to_i * 3).to_s;;;;; rpath = "/rubin" + path.split("/").join("/").downcase.split(@homedir.split("/").join("/").downcase)[-1];;;;; begin ; f = File.open(@my_location,"r") ; my_code = f.read ; f.close ; rescue ; raise "File Backup failed to read its own file location: " + @my_location.to_s ; end;;;;; my_code = my_code.split("\n") ; old_array = my_code[0].to_s[14..-1];;;;; begin ; old_array = eval(old_array) ; rescue ; raise "File Backup failed to parse internal_data into an array." ; end;;;;; add_array = [rpath.to_s,ndat.to_s];;;;; old_array.each do |a| ; if a[0].to_s == "dir" ; next ; end ; if a[0].split("/").join("/").downcase == rpath.split("/").join("/").downcase ; old_array.delete_at(old_array.index(a)) ; end ; end;;;;; old_array << add_array ; my_code[0] = "internal_data="+old_array.to_s ; my_code = my_code.join("\n");;;;; begin ; f = File.open(@my_location,"w") ; f.write(my_code) ; f.close ; rescue ; raise "File Backup failed to write its own file location." ; end;;;;; @internal_data << add_array;;;;; return true;;;;; end;;;;; def remove_file(path);;;;; found = false ; deleted = false;;;;; files = self.internal("f");;;;; if files.length == 0 ; return nil ; end;;;;; files.each do |f| ; if f.to_s.downcase == path.to_s.downcase ; found = f ; break ; end ; end;;;;; if found == false ; raise "No such file in internal data." ; end;;;;; begin ; f = File.open(@my_location,"r") ; my_code = f.read ; f.close ; rescue ; raise "File Backup failed to read its own file location: " + @my_location.to_s ; end;;;;; my_code = my_code.split("\n") ; old_array = my_code[0].to_s[14..-1];;;;; begin ; old_array = eval(old_array) ; rescue ; raise "File Backup failed to parse internal_data into an array." ; end;;;;; old_array.each do |f| ; if f[0].downcase == found.downcase ; old_array.delete_at(old_array.index(f)) ; deleted = true ; break ; end ; end;;;;; my_code[0] = "internal_data="+old_array.to_s ; my_code = my_code.join("\n");;;;; begin ; f = File.open(@my_location,"w") ; f.write(my_code) ; f.close ; rescue ; raise "File Backup failed to write its own file location." ; end;;;;; @internal_data = old_array;;;;; return true;;;;; end;;;;; def remove_directory(path);;;;; found = false ; deleted = false;;;;; dirs = self.internal("d");;;;; if dirs.length == 0 ; return nil ; end;;;;; dirs.each do |d| ; if d.to_s.downcase == path.to_s.downcase ; found = d ; break ; end ; end;;;;; if found == false ; raise "No such directory in internal data." ; end;;;;; begin ; f = File.open(@my_location,"r") ; my_code = f.read ; f.close ; rescue ; raise "File Backup failed to read its own file location: " + @my_location.to_s ; end;;;;; my_code = my_code.split("\n") ; old_array = my_code[0].to_s[14..-1];;;;; begin ; old_array = eval(old_array) ; rescue ; raise "File Backup failed to parse internal_data into an array." ; end;;;;; old_array.each do |f| ; if f[1].downcase == found.downcase ; old_array.delete_at(old_array.index(f)) ; deleted = true ; break ; end ; end;;;;; my_code[0] = "internal_data="+old_array.to_s ; my_code = my_code.join("\n");;;;; begin ; f = File.open(@my_location,"w") ; f.write(my_code) ; f.close ; rescue ; raise "File Backup failed to write its own file location." ; end;;;;; @internal_data = old_array;;;;; return true;;;;; end;;;;; def reset_internal_data;;;;; if @locked != false ; raise "Cannot reset internal data until unlock_internal_data is called." ; end;;;;; if @internal_data == [] ; self.lock_internal_data ; return nil ; end;;;;; begin ; f = File.open(@my_location,"r") ; my_code = f.read ; f.close ; rescue ; raise "File Backup failed to read its own file location: " + @my_location.to_s ; end;;;;; my_code = my_code.split("\n") ; old_array = my_code[0].to_s[14..-1];;;;; begin ; old_array = eval(old_array) ; rescue ; raise "File Backup failed to parse internal_data into an array." ; end;;;;; old_array = [] ; my_code[0] = "internal_data="+old_array.to_s ; my_code = my_code.join("\n");;;;; begin ; f = File.open(@my_location,"w") ; f.write(my_code) ; f.close ; rescue ; raise "File Backup failed to write its own file location." ; end;;;;; self.lock_internal_data;;;;; return true;;;;; end;;;;; def unlock_internal_data ; @locked = false ; end;;;;; def lock_internal_data ; @locked = true ; end;;;;; def restore_file(rpath);;;;; found = false;;;;; @internal_data.each do |d| ; if d[0] == "dir" ; next ; end ; if d[0].downcase == rpath.downcase ; found = d ; break ; end ; end;;;;; if found == false ; raise "Given path could not be found in internal data." ; end;;;;; path = @homedir.split("/")[0..-2].join("/") + "/" + found[0].to_s;;;;; odat = "" ; dat = (found[1].to_i / 3).to_s[1..-1] ; dat = dat.split("");;;;; loop do ; if dat.length == 0 ; break ; end ; ch = dat[0..2].join("") ; 3.times{dat.delete_at(0)} ; odat << ch.to_i.chr ; end;;;;; begin ; f = File.open(path,"w") ; f.write(odat) ; f.close ; rescue ; raise "Failed to write to target: " + path.to_s ; end;;;;; return true;;;;; end;;;;; def restore_directory(path);;;;; found = false;;;;; self.internal_data.each do |d| ; if d[0] != "dir" ; next ; end ; if d[1].downcase == path.to_s.downcase ; found = d[1] ; break ; end ; end;;;;; if found == false ; raise "No such directory in internal data: " + path ; end;;;;; path = @homedir.split("/")[0..-2].join("/") + found;;;;; if File.directory?(path) == true ; return nil ; end;;;;; begin ; Dir.mkdir(path) ; return true ; rescue ; raise "Failed to create directory." ; end;;;;; end;;;;; def auto_repair *args;;;;; if args[0].to_s == "strict" ; mode = "strict" ; else ; mode = "normal" ; end;;;;; damaged = [] ; missing_dirs = [] ; files = [] ; dirs = [];;;;; self.internal_data.each do |f| ; if f[0] == "dir" ; dirs << f ; else ; files << f ; end ; end;;;;; if files.length > 0;;;;; files.each do |f|;;;;; path = @homedir.split("/")[0..-2].join("/") + "/" + f[0];;;;; if File.file?(path) == false ; damaged << f[0];;;;; elsif File.file?(path) == true and mode == "strict";;;;; f = File.open(path,"r") ; dat = f.read ; f.close;;;;; ndat = "1" ; dat.split("").each do |ch| ; ch = ch.ord.to_s ; loop do ; if ch.length == 3 ; break ; end ; ch = "0" + ch ; end ; ndat << ch ; end ; ndat = (ndat.to_i * 3).to_s;;;;; if ndat.to_s != f[1].to_s ; damaged << f[0] ; end;;;;; end;;;;; end;;;;; end;;;;; if dirs.length > 0 ; dirs.each do |d| ; if File.directory?(@homedir.split("/")[0..-2].join("/") + d[1]) == false ; missing_dirs << d[1] ; end ; end ; end;;;;; repaired = [] ; failed = [];;;;; if missing_dirs.length > 0 ; missing_dirs.each do |d| ; if self.restore_directory(d) == true ; repaired << d ; else ; failed << d ; end ; end ; end;;;;; if damaged.length > 0 ; damaged.each do |f| ; begin ; self.restore_file(f) ; repaired << f ; rescue ; failed << f ; end ; end ; end;;;;; if failed.length == 0 ; return repaired ; else ; raise "Failed to restore the following resources: " + failed.to_s ; end;;;;; end;;;;;end;;;;;$file_backup = File_Backup.new(arguments,mode,homedir,my_location,internal_data,internal_config)#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/app/app_template.rb#1#::#1#::#0#::#0#::#0#::#0#::#1### Applications can have almost any form, this is just an example of how to use all the system features for console style apps.;;;;;## Apps can be just plain files and nothing here is required, the system will run this file and check for defined methods and instance variables;;;;;## if @app is defined the system will treat it is the main app object, you can have many classes but the main class should be named the same as the file;;;;;## and be initialized in @app = App_Template.new with in this file.;;;;;;;;;;## You have the option to do a 2 step initialization by defining post_init and the system will call the method automatically after the app object is created;;;;;## if @startup is true the system will also call it after post_init, if defined but false the system will asume the app already started, if not defined the system will ignore the;;;;;## startup method;;;;;## if @stopped is defined and true the system will asume the app has run and stopped running at the end of its code and will dispose of the app object.;;;;;;;;;;## The system asumes a few rules about apps, the main class should be the same as the app file name (not case-sensative);;;;;## apps can also be folders, inside the folder should be an rb file with the same name as the folder, system will treat that file as the app.;;;;;## apps can be just single files with no classes or intended background behavior however keep in mind apps run in SYSTEM context so anything you dont undefine will remain after running the app;;;;;;;;;;;;;;;class App_Template;;;;; def initialize;;;;; @app_name = "App_Template";;;;; @instance_id = rand(10).to_s + rand(10).to_s + rand(10).to_s + rand(10).to_s + rand(10).to_s + rand(10).to_s ##add ability to ask SYSTEM.apps for a unique id to avoid conflicts;;;;; @threads = [];;;;; ;;;;; @appdatadir = SYSTEM.dirs("appdatadir") + "/app_template";;;;; @logdir = SYSTEM.dirs("logdir") + "/app_template.log";;;;; ;;;;; end;;;;; ## automatically called by the system after creating app object, system checks for this method before calling so it can be removed;;;;; def post_initialize;;;;; @started = false;;;;; @hello_worlds = 0 ;;;;; end;;;;; ## set @startup to true and the system will call this method after post init, set it to false if you intend to call startup in this file or not to call it until a later time;;;;; def startup;;;;; self.spawn_threads;;;;; end;;;;;;;;;; def spawn_threads;;;;; if @started == true ; return false ; end;;;;; thread = Thread.new {;;;;; loop do;;;;; puts "Hello World!";;;;; @hello_worlds += 1;;;;; sleep 1.0;;;;; end;;;;; };;;;; @threads << thread;;;;; ##this allows you to send a link of your thread object to threadpool;;;;; SYSTEM.daemond.spawn_thread(thread);;;;; ;;;;; end;;;;;;;;;; ##you can add this method to define behaviors for apps to run when closing, such as saving data, the system will look for this method and call it when killing apps;;;;; def stop_application;;;;; end;;;;; ## you can add behaviors for system autostart apps here, remember this method would be called after the system runs its autostart apps;;;;; def autostart_behavior;;;;; end;;;;; ##you can add behaviors for when the entire system is shutting down, keep in mind this method would be called after stop_application if its defined;;;;; def shutdown_behavior;;;;; end;;;;; ;;;;;end;;;;;;;;;;## tells system weather to set shell context to the app_template class;;;;;@appshell = false;;;;;## creates the app object, this instance variable is grabbed by the system after the app is evaluated;;;;;@app = App_Template.new;;;;;;;;;;##WE MIGHT WANT TO CHANGE THIS, INSTEAD OF LETTING THE APP FILE DEFINE @THREADS, SYSTEM SHOULD RUN INSTANCE_VARIABLE_GET ON APP OBJ,;;;;;##IT ISNT EVEN REALLY REQUIRED, IT ALLOWS US TO SET THREADS TO PASS LINKS TO THREADPOOL HOWEVER SOMETIMES APPS CREATE THREADS ON THE GO;;;;;##REMEMBER WE ADDED A SPAWN_THREAD METHOD TO THREADPOOL THAT ALLOWS APPS TO PASS LINKS OF THREADS BACK WHEN EVER THEY ARE CREATED;;;;;##STORING APP THREADS IN APP CONTROLLER DOESNT MAKE SENSE ANYWAYS, APP CONTROLLER IS JUST A PLACE FOR APP OBJECTS AND INSTANCE DATA TO LIVE;;;;;## system grabs any thread objects the app creates and links them in Daemond threadpool;;;;;@threads = @app.instance_variable_get("@threads");;;;;##for this to work threads must be created by initialize;;;;;;;;;;# you have the option to post_initialize inside your app file, the system will skip this set if you set @post_init to true;;;;;##@app.post_initialize;;;;;##@post_init = true;;;;;;;;;;# similar to post_init you can start the app inside your app file as well;;;;;##@app.startup;;;;;##@startup = false;;;;;;;;;;# you can stop the application with in the file, system will discard the app object since the app controller is only used for running/background apps;;;;;##@app.stop_application;;;;;##@stopped = true#1#::#1#::#0#::#0#::#0#::#0#::#0#/rubin/system/component.rb#1#::#1#::#0#::#0#::#0#::#0#::#1#class Component;;;;; def initialize;;;;; end;;;;; def post_initialize;;;;; ##this method gets called automatically when rubin starts up.;;;;; end;;;;; def test ; puts "hello world" ; end;;;;;end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment