import java.util.*; import java.util.zip.*; import java.util.List; import java.util.regex.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.concurrent.locks.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.text.*; import javax.swing.table.*; import java.io.*; import java.net.*; import java.lang.reflect.*; import java.lang.ref.*; import java.lang.management.*; import java.security.*; import java.security.spec.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; import javax.imageio.*; import java.math.*; import javax.swing.border.TitledBorder; import javax.swing.border.*; import java.text.*; import javax.swing.undo.UndoManager; import java.nio.charset.Charset; import java.text.NumberFormat; import java.awt.datatransfer.StringSelection; import javax.imageio.metadata.*; import javax.imageio.stream.*; import java.text.SimpleDateFormat; import javax.swing.event.AncestorListener; import javax.swing.event.AncestorEvent; import javax.swing.Timer; import java.util.TimeZone; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; import java.awt.geom.Rectangle2D; import java.nio.file.Path; import javax.swing.filechooser.*; class main { // AI begins here static String substring(String s, int x) { return substring(s, x, strL(s)); } static String substring(String s, int x, int y) { if (s == null) return null; if (x < 0) x = 0; int n = s.length(); if (y < x) y = x; if (y > n) y = n; if (x >= y) return ""; return s.substring(x, y); } // convenience method for quickly dropping a prefix static String substring(String s, CharSequence l) { return substring(s, lCharSequence(l)); } public static String join(String glue, Iterable strings) { if (strings == null) return ""; if (strings instanceof Collection) { if (((Collection) strings).size() == 1) return str(first(((Collection) strings))); } StringBuilder buf = new StringBuilder(); Iterator i = strings.iterator(); if (i.hasNext()) { buf.append(i.next()); while (i.hasNext()) buf.append(glue).append(i.next()); } return buf.toString(); } public static String join(String glue, String... strings) { return join(glue, Arrays.asList(strings)); } static String join(Iterable strings) { return join("", strings); } static String join(Iterable strings, String glue) { return join(glue, strings); } public static String join(String[] strings) { return join("", strings); } static String join(String glue, Pair p) { return p == null ? "" : str(p.a) + glue + str(p.b); } static int lastIndexOf(String a, String b) { return a == null || b == null ? -1 : a.lastIndexOf(b); } static int lastIndexOf(String a, char b) { return a == null ? -1 : a.lastIndexOf(b); } // starts searching from i-1 static int lastIndexOf(List l, int i, A a) { if (l == null) return -1; for (i = min(l(l), i) - 1; i >= 0; i--) if (eq(l.get(i), a)) return i; return -1; } static int lastIndexOf(List l, A a) { if (l == null) return -1; for (int i = l(l) - 1; i >= 0; i--) if (eq(l.get(i), a)) return i; return -1; } static String padLeft(String s, char c, int n) { return rep(c, n - l(s)) + s; } // default to space static String padLeft(String s, int n) { return padLeft(s, ' ', n); } static String trim(String s) { return s == null ? null : s.trim(); } static String trim(StringBuilder buf) { return buf.toString().trim(); } static String trim(StringBuffer buf) { return buf.toString().trim(); } static class Smarty extends Concept { static final String _fieldOrder = "IntensityRange Sense Processing50 MaxBodies World bodies VB_Name JND Smarty LeftArrow RightArrow UpArrow DownArrow FourWay Smarty0 BodySetting BodyConfig BodyValue BodyPointing North East South West NumSenses MaxSenses IsSense Senses SensorStimuli PropertyBinonType SymbolicOrMagnitude LowerRangeLimit UpperRangeLimit LinearOrCircular IntegersOrLogs NumberOfSensors SensorsDependentOrIndependent Symbolic Magnitude Linear Circular IntegerValues LogValues Dependent Independent SensorValues Valu XQCnt NoName Motion NoMove WheelMovement ABlock Wall EmptySquare Fired Current NumDevices MaxDevices Device IsDevice Devices DeviceResponses DeviceValues NoResp WheelsTurn MoveForward MoveToLeft MoveToRight MoveBackward TurnRght TurnLft TurnArnd NoMoveOrTurn NumActs RotateActs NumBinons MaxBinons OverLimit Binons BType O1 TQ O2 GQ IDL IntVl OLv SP TriggerList TriggerCount GoalList GoalCount AE NullObject NOVEL INTERESTING FAMILIAR NoInterest InterestLevels Sequential Parallel Action Attention MaxBinonTypes NumBinonTypes BinonTypeName BinName BinAbbreviation BinonTypes ActBin NumProperties NullType SensOrDevNum SensedBinons NumPercepts MaxPercepts Percepts BinId PerceptSources FirstSource SecondSource PerceptLevel NumTargets MaxTargets Targets NLnk TargetBinon NullTarget NumDHabits TopLevel HighestPerceptLvl MaxLevels STM TQCnt MoveAmount PerceivedBinon LTMEMORY LtmPerceptTyp LtmPerceptBin LtmESType LtmESActBin LtmARType LtmARActBin LtmActionTyp LtmActionBin StoreAt MaxMemory INPUTS OUTPUTS SizeBase IntensityBase ASpace SequentialSign ParallelSign CreateAll Normal Happy Unhappy PartMatch DoingReaction DoingRepeat LastAct LIN COUNTIN RecentWorld RecentBody OperatingMode Running Started vbDblQuote Black White LightBlue DarkBlue"; int IntensityRange; String[] Sense = new String[10 + 1]; boolean Processing50 = false; int MaxBodies; transient TheWorld World; Bodies bodies = new Bodies(); static class TheWorld { public String LookUnder() { return ""; } public void MoveWest() { } public void MoveSouth() { } public void MoveEast() { } public void MoveNorth() { } public void PointUnder() { } public void PointNorth() { } public void PointSouth() { } public void PointWest() { } public void PointEast() { } public void DisplayStimuliAndResponse(int[][][] sensorValues, char resp) { } public int RangeSouth() { return 0; } public int RangeNorth() { return 0; } public int RangeEast() { return 0; } public int RangeWest() { return 0; } public String LookSouth() { return ""; } public String LookNorth() { return ""; } public String LookEast() { return ""; } public String LookWest() { return ""; } public void Update_View() { } public void setBinonDisplayObjList(String text) { } public void setBinonDisplayChngResults(String text) { } public void appendBinonDisplayChngResults(String text) { } public void showSensorValues(String text) { } public void showDeviceValues(String text) { } } // end of TheWorld String VB_Name = "Adaptron"; // Originally was a TEST VERSION WHICH PRODUCES RANDOM INPUT AND // CHECKS MEMORY TO SEE IF IT CONTAINS THE SAME STUFF // Obviously must have spun it off of Think 5 // Adaptron/Cognitron Algorithm - Program - Feb. 2003 test // (C) Copyright 2007, Adaptron Inc. // // THINK3 IS NOT HANDLING CONSCIOUS HABITS PROPERLY // THINK4 IS EXPERIMENT IN EXPECTATIONS BEING SAVED // THINK5 DOES A PROPER JOB OF HANDLING R-HABITS // 11 July 2002 - attempting to get the 2 bugs out of pattern matching // 13th July 2002 - put back the stimulus matching mem location use for // habit continuation checking in the right order - resulting stimulus // first then is it an expected trigger. // pattern4 - July 28, format display better // pattern5 - July 29 week - trace display improvements -got out bug in // habit collapsing // pattern6 - Aug 3 - test some more // pattern7 - Aug 9 - more tests with manual input, THEN AUTOMATED AGAIN // pattern8 - Aug 13 - I did top and bottom expected stimuli in habit in // previous version - now I need to introduce expected stimuli // in the habit stack fixed up Context saving too - but I think // some context could be put in LTM for pattern matching on // context so it doesn't get too long or do pattern matching on // context while in STM. // Pattern9 - incorporate thinking changes from Think8 and turn on responses // Went back to the THINK versions and incorporated results from Pattern9 // THINK7 DOES A PROPER JOB OF HANDLING R-HABITS // THINK8 Well documented version // Fixed up some stuff and comments and made it into ACTIONS8.BAS Aug 16th 2002 // ACTIONS8 - Work on comments and then responses -Then went back to Pattern // versions and worked on Pattern0 -Active Habits that fail attract attention // and then incorporated these results into Actions8. // Actions9 - Started to investigate response habits - fixed up // NOADDSHABITS and removed NOADDHABITS. // ACTION10 - Make no distinction between doing nothing and doing something // until the last minute when go to do it. // - Refine priority of what attracts attention especially for // familiar input. // EXPLORE1 - Test it out // EXPLORE2 - Improve context saving. Use 16 bit memory locations. // - HAVING PROBLEM WITH HABIT MATCHING - CREATE NEW VERSION // EXPLORE3 - Change habit stack so current one is on top and any ADDSHABITS // are below it. Stopped it using context in habits being done. // EXPLORE4 - Removed code for context saving. // Explore5 - Visual Basic 6 Version with different windows for LTM, STM etc. // Boredom turned on for current stimulus and result // habitualized and this habit has a familiar or novel result // based on InterestLevel. Old Boredom code commented out. // Explore6 13th July 2003 Try to make feelings of novel, familiar etc. // into a new stimulus type which result in information about // success or failure. // 12th Aug 2003 Decided not to do this. Instead am // going to add R-Habits. Decided R-Habits already taken care // of. Added continuous stimuli from both senses. Investigate // looping behaviour and subconscious habit execution. Haven't // done looping but it seems pretty stable. // Explore7 11th Sept 2003 Now work on subconscious habit execution. // Add loop execution in subconscious habits // 24th Sept Allow multiple stimuli on S-List - 1 external & // 1 internal stimulus. Then fix bugs / features // Explore8 1st Oct 2003 Now work on R-habits and their execution. // Explore9 6th Nov 2003 Major change required in how memory stored and // used - less emphasis on efficiency and episodic accuracy. // Added multiple S-habit recognition and context of S-habit // Added conscious looping of permanent S-habits // Happy1 25th Nov 2003 Add in pain and pleasure. 11th Dec Added // expectation of Novel as Interesting - exploration is better. // Happy2 17th Dec 2003 First attempt at adding thinking // 7th Jan 2004 small changes // Happy3 10th Jan 2004 turn off separate Trigger and Result stimuli, // add control flags for it and DoingReflex. // Happy4 13th Jan,Seperate permanence property from feeling for stimuli // Add Response Habits containing Response-Stimulus-Response // Get looping (repeating same stimulus) working properly // Happy5 20th Jan, getting permanent working, remove stimulus roles // Happy6 21st Jan, handle dynamic environments // Happy7 23rd Jan, Try handling S-Habits as R-Habits-no go. // Happy8 27th Jan, Try to get R-habits as R-S-R working. Feb 12th. Add // subconscious processes. // Happy9 23rd Feb, Novel stimulus becomes interesting, then familiar // Enhance thinking, strategies for handling Interesting // Works1 6th Mar, 2004, Attend to stimuli // Works2 30th March, Expectation processing // Works3 31st March, Stimulus context in LTM for S-Habits too. // Works4 8th Apr, Recognize loops in R-Habits, Good/Bad testing // Works5 15th Apr, turn on Kinesthetics, do subconscious habits // Works6 work on repetition / loops // Works7 18th July 2004, new learning strategy, Test Cases // Works8 29th July, Good and Bad processing // Works9 7th Sept, Generalization & Discrimination - 2 or more senses // and subconscious habit processing // Learn1 18th Sept, Conscious versus subconscious behaviour, added // levels and context at end of LTM // Learn2 3rd Nov, Kinesthetic stimuli, loops, action habits // Learn3 23rd Nov, Rename things, subconscious A-Habits, A-sequences // Learn4 6th Dec, Chained A-Habits, Concentration, A-Sequences // Learn5 6th Jan, 2005, A&B sequence, thinking refined, kinesthtics, // order of For's, Separate world // Learn6 World front-end, ABC repeating pattern & permanent S-Habits // Learn7 Body info, still working on S-Habits, R-Habits, separate body // Learn8 11 May 05, separate body & Test Cases, R-Habits, P-Stimuli, // Difference in R-Habits // Learn9 21 June 05, 31st Dec 05, removed linked habits, novelty/familarity // stored as feeling, work on 2nd sense and R-Habits // Habit1 3rd March 06, New attention algorithm, only collapse permanent // triggers of S-Habits, practice non-permanent S-Habits // Habit2 March - Interestlevel based on A & S-Habit feelings // Habit3 March - Good & Bad, Reward & Punishment, Feelings // Habit4 Jan 2007 reworking interest levels // Habit5 29th Jan 07, S-habits collapse when both stimuli are permanent // A-habits interest propagate back to trigger, S-Habits interest // propagates up the heirarchy. // Habit6 16th Feb 07, Rearrange attention algorithm // Habit7 14th March 07, Add graduated stimuli // Habit8 25th March 07, New attention algorithm // Habit9 3rd April 07, Sort out permanent stimuli, attention algorithm // Cogni1 18th April 07, Work on thinking part, replace feature with sensor // Recog1, Recog2 Recognition of objects from graduated senses. // Add discrete Sensor Array, discrete and graduated sensors // Cogni2 New interest derivation for experiences, new expected interest // Cogni3 27th July 07, Each Habit has its own expected interest // In here I worked on lines // Cogni5 Sept 07, Reworking multiple sensors with graduated values // Cogni6 Oct 12, 07, New S-Habit matching and find difference, multi-sensors // Cogni7 Oct 28, 07, Multi-sensors // Cogni8 Nov 16, 07, Use recency to solve which S-Habit to attend to. Change // action selection strategy, use FindInstead, not FindDifference // Cogni9 Nov 25, 07, Bucket stimuli readings, Change as a stimulus // Grad1 Dec 14, 07, Graduated sensors, S-Habits use LTM pointers // Grad2 Feb 4, 2008, sequences of graduated stimuli - C-Habits, generalization // Grad3 Feb 14, 2008, Change as stimulus, new S-Habit structure // Grad4 Feb 26, 2008, new S-Habit structure // Grad5 Mar 9, 2008, new S-Habit structure // Grad6 April 2008, Remove Change as a stimulus - objects represent the changes experienced // In here I worked on lines and developed course 447 // Grad7 Jan 2009, Subconscious action habits, Interest levels // Grad8 Feb 2009, new S-Habit structure changes // Grad9 Mar 20, 2009, Overlapping parts of S-habits, add line recognition from Sense1 // Ideas1 April 18, 2009, Add change objects, get thinking working and upto testcase #25 // Ideas2 May 19, 2009, Use tree of sense stimuli and P-habits - not on S-List // Ideas3 June 17, 2009, Finish conversion of S-List, Conscious Habit rework, attention alg. // Ideas4 July 8, P-Habits // Ideas5 July 10, Remove context processing, ignore repeating S-Habits, // Ideas6 Aug 2, Incorporate new line recognition, Where and Order processing // Ideas7 Sept 1st, Partial trigger matching - generalization // Ideas8 Sept 15th, Graduated readings, 8th Dec new recognition routines, Change Reading Object // Ideas9 Dec 15th, Separation object // Change1 Dec 31st, Save Change objects in LTM, Add STM for sequences // Change2 Jan 10th, 2010 create SepRdgObj, remove LTM Separs(), move STM process // Change3 Feb 2nd, STM processing, new line recognition, sequence recognition // Change4 May 2nd, New LTM episodic memory representation, new STM // Change5 May 26th, Sequence and Action LTM separated // Change6 Jun 13th, new Where obj, STM per Sense & Sensor if independent // Change7 Jun 23rd, Interest on sequences in STM, T-List // Change8 Jul 4th, P-Habits in STM, Body and World changes // Change9 Jul 20th, A_Sequences implemented, Fix STM S-habit recognition / distraction // Active1 Jul 31st, Boredom and sub-conscious A-Habits // Active2 Aug 12th, Conscious STM and/or A-Habits // Active3 Sept 21st, New Sequence recognition, Conscious STM // Active4 Oct 7th, Action Habits(practicing & doing), remove partial sequential match, // Convert interest into a property of all binons // Active5 Nov 4th, New binon structure, thinking // Active6 Dec 7th, Another new binon structure, fix partial match, remove reset interest // Active7 Dec 17th, Separate Change and Interest, reduce interest upon repetition, no concentration // Active8 Jan 22nd, 2011 remove permanent, remove current habit, separate S-habit and A-Habits // Active9 Feb 12th, New binon structure, P-habits before Sequences, better attention // Expect1 Mar 6th, Expect Interesting, new A-Habit structure, remove dependence concept // Expect2 Mar 23rd, Changed DoIt structure, Experiences in STM, Conscious Seq's in STM // Expect3 Apr 9th, New Acton structure, sequential trigger and goal recognition, removed // Novel and Fresh concepts // Expect4 May 3rd, Add device stimuli, Unexpected, New Acton structure // Expect5 Aug 2nd, Action habits, STM changes // Expect6 Sept 4th, STM just recognizes (no expectations), remove orient actons, directed // attention on expected goal // Expect7 Sept 20th,Added UnInteresting // Expect8 Oct 4th, New acton structure // Expect9 Oct 16th, P-Habits, kinesthetic sense fixed, formation of combo by A-Habit? // Practic1 Nov 7th, Sequences and Action Habits // Practic2 Nov 15th, STM processing and Permanent // Practic3 Dec 12th, Before and after conscious STMs, S-Level 1 stimuli familiar // Practic4 Jan 10th, STMs do not create A-Habits, Practice mode - redo-interest // Practic5 Jan 31st, Practice and Goal Actons, STM processing conscious sequences // Practic6 Feb 15th, P-Habit processing, Directed Attention, sequences of permanent stimuli // Practic7 Mar 14th, brought in new pattern recognition // Practic8 Apr 7th, new novel/familiar combinations and STM processing, P-Habits working // Practic9 Apr 24th, generalization for 2 senses // General1 May 23rd, Incorporate new Object Recognition (twice) // General2 July 1st, Practice and Thinking, Redo versus goal interest, Random next responses // General3 July 11th, A-habits at lowest level first, Unexpected sequential interest // General4 July 23rd, Expectation inhibits familiar from attention, should binons come with // habituation of a repeat sequence built in? // General5 12th Jan 2017 - started to document it - going to insert PerceptionAction from Act2 // 15th Jan 2017 'Inserted PerceptionAction() and got Inpu_KeyPress(0 and TestCases working with no babbling output. // 22nd Jan 'adding motor babbling when known action habits are familiar // 23rd Jan 'thinking and bodies starting to work // 24th Jan 'adding body #6 with two senses - vision and motion // 28th Jan 'Got Thinking Approach #1 working // 29th Jan 'Make Binon type one of the Binon properties // 30th Jan 'Create P-Habit combinations for any number of senses = properties // 2018 Aug 29th 'Clean up code before sending to Jianyong // 31st Aug 'Renamed it Smarty. Continue to clean up the code // 25th August 2019 // 'renaming percpts, actions etc. to conform with the perception-action hierarchy paper // DefInt A - Z; //16 bits / 2 bytes // set to 20% int JND; // J = wingdings happy face final static String Smarty = "J"; // "<" final static String LeftArrow = chr(239); // ">" final static String RightArrow = chr(240); // "^" final static String UpArrow = chr(241); // "v" final static String DownArrow = chr(242); // "+" - unused String FourWay; // "Smarty0" The initial / default Body name String Smarty0; // Contains the current body being used String[] BodySetting = new String[22]; // Bodysetting$(0) contains the number of settings in use // The values in the configure forms when go to Design or Select String BodyConfig; // For determining if a change has been made. // Contain the values read and written to the .BDY file String[] BodyValue; // The values on the body configuration forms // direction body is pointing, 0=East, 1=South, 2=West, 3=North int BodyPointing; // direction body is pointing, 0=East, 1=South, 2=West, 3=North transient final int North = 3; transient final int East = 0; transient final int South = 1; // direction body is pointing, 0=East, 1=South, 2=West, 3=North transient final int West = 2; // -------------------------- Senses and Sensors -------------------------- // The number of physical senses, Max of 10, dynamically set in SetUpSense() int NumSenses; // Currently equals the NumProperties since each sense currently = 1 property type // Maximum number of senses = max 10 physical senses int MaxSenses; // 1, Flag for Senses versus Devices int IsSense; // unused String StringSense; //Names of senses, up to 10 physical senses - assigned in SetupSense() // Properties of the different senses int[][] Senses = new int[10 + 1][8 + 1]; // 1st index = Sense number // 2nd index = Sense property // A string of the possible symbolic stimuli for the sensor String[] SensorStimuli = new String[10 + 1]; // ---- Senses() - 2nd index values - Sense Properties - same used for Devices below // 1, Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin int PropertyBinonType; // 2, Symbolic or Magnitude indicator int SymbolicOrMagnitude; // 3, Lower limit of range of values, zero is minimum (65 = "A") int LowerRangeLimit; // 4, Upper limit of range of values, 255 is maximum (90 ="Z") int UpperRangeLimit; // 5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360) int LinearOrCircular; // 6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs int IntegersOrLogs; // 7 Number of sensors in sensor array int NumberOfSensors; // 8 are sensors adjacent (dependent) or independent int SensorsDependentOrIndependent; // 1, Indicates that the values from this sense are symbolic, range A -> Z int Symbolic; // 2, Indicates that the values from this sense are numeric, integers, range 0 -> Limit int Magnitude; // 1, Indicates that the values go from the lower limit to upper limit int Linear; // 2, Indicates that the values rap around from the upper limit to 0 int Circular; // 1, Indicates that the values are integer readings int IntegerValues; // 2, Indicates that the values are already logs - orders of magnitude int LogValues; // 1, Sensors in array are beside each other (adjacent) int Dependent; // 2, Sensors are not associated with each other int Independent; // -------------------- Values of stimuli from senses / sensors ------------------------------ // Stimulus values from senses/sensors int[][][] SensorValues = new int[10 + 1][2 + 1][1 + 1]; // 1st index is sense number, currently = property /sense binon type // 2nd index is what type of information is in the SensorValues(), XQCnt or Valu // 3rd index is Fired for the most recent stimulus value and Current for the previous // ---- SensorValues 2nd index values - type of information in SensorValues() // =1, the value for the stimulus, if symbolic then value = Asc(Symbol$) int Valu; // =2, the count of times the value has repeated, also used below int XQCnt; // "_", The character used when no letter provided for the IDL value of a TextBin binon String NoName; // World.MoveDown() etc set this to indicate the direction the robot moved String Motion; // "-" to indicate there was no motion in the Motion$ stimulus value String NoMove; // "-flrb..." 'will contains the possible wheel motions String WheelMovement; // WheelMovement$ = "-flrb" & TurnRght$ & TurnLft$ & TurnArnd$ ' rotate right, left and around 180 degrees String ABlock; // a block, Chr$(219) is a black square in Terminal font static final String Wall = chr(219); // Chr$(177) is a fuzzy square in Terminal font static final String EmptySquare = chr(177); // ---- SensorValues 3rd index values - which past stimulus it is - also used below // =0 'stimulus put in this level upon firing before being processed int Fired; // =1 'The Fired one becomes the Current one after processing int Current; // -------------------- Devices ------------------------------------------------ // Number of output devices - max 4 - dynamically set in SetupDevice() int NumDevices; // Maximum number of devices = max 4 devices int MaxDevices; // Names of device, up to 4 devices - assigned in SetupDevice() String[] Device = new String[4 + 1]; // 2, Flag for Devices versus Senses int IsDevice; // Properties of the output / response devices int[][] Devices = new int[4 + 1][6 + 1]; // 1st index = Device number // 2nd index = Device property // A string of the possible symbolic responses for the device String[] DeviceResponses = new String[4 + 1]; // ---- Devices() - 2nd index values - Device Properties - DEFINED ABOVE // Public PropertyBinonType '1, Response property binon type e.g. 1 = LetrBin // Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator // Public LowerRangeLimit '3, Lower limit of range of response values, zero is minimum (97 = "a") // Public UpperRangeLimit '4, Upper limit of range of response values, 255 is maximum (122 = "z") // Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Motor rotations are Circular (0 to 360) // Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs // Public Symbolic '1, Indicates that the values for this device are symbolic, Range a -> z // Public Magnitude '2, Indicates that the values for this device are numeric, integers, range 0 -> limit // Public Linear '1, Indicates that the values go from the lower limit to upper limit // Public Circular '2, Indicates that the values rap around from the upper limit to 0 // Public IntegerValues '1, Indicates that the values are integer readings // Public LogValues '2, Indicates that the values are already logs - orders of magnitude // -------------------- Values of responses to devices ------------------------------ // Response values for devices int[][] DeviceValues = new int[4 + 1][2 + 1]; // 1st index is device number, currently = response property binon type // 2nd index is what type of information is in the DeviceValues(), XQCnt or Valu // ---- DeviceValues 2nd index values - type of information in DeviceValues() - DEFINED ABOVE // Public Valu '=1, the value for the response, if symbolic then Symbol$ = Chr$(value) // Public XQCnt '=2, the count of times the value needs repeating, also used below // "-", The character representing no response for a LetrBin binon transient final char NoResp = '-'; // c Public Relax$ '"-", used for a Relaxing response - currently the same as NoResp$ // and it is used as the stimulus input of the Motion sense // If it is false then Smarty displays as an O else it displays as ^>1 means it has more than one goal int TriggerCount; // Used for prediction reliability, may be set >1 if needs to be combined with previous // 12, points to the linked list of target binons [Targets()] int GoalList; // for which this binon is the right source binon (not the left source binon) // 13, Count of its sequential left targets, >1 means can not predict its trigger int GoalCount; // Used for reliability of determining the cause, may be set >1 if needs to be combined with next // 14, Action (Percept - Act) or Attention (Act - Percept) level 1 Sequential binon int AE; // -1, Indicates the O1 or O2 pointer is not pointing to another binon int NullObject; // ---- Interest values for Binons(x, IntVl) - must be numeric for comparison purposes // New - 1st time experienced - attention paid to it // ---- Interest values for Binons(x, IntVl) - must be numeric for comparison purposes // 3 New - 1st time experienced - attention paid to it final int NOVEL = 3; // To indicate it has been experienced for the second time // 2 To indicate it has been experienced for the second time final int INTERESTING = 2; // Neutral, experienced 2 or 3 or more times // 1 Neutral, experienced 2 or 3 or more times final int FAMILIAR = 1; // -1 Interest not known yet int NoInterest; // 2 or 3 - number of interest levels, 2= Novel and Familiar, 3= Novel, Interesting, and Familiar int InterestLevels; // ---- Sequential or Parallel property values for Binons(x, SP) // -1 int Sequential; // +1 int Parallel; // ---- Action or Attention property values for Binons(x, AE) - value = 0 for Parallel Percepts // 1 int Action; // 2 int Attention; // ---- BinonType property values for Binons(x, BType) // with 2 senses and 1 device this is =6, 4 senses & 4 devices = 33 int MaxBinonTypes; // = 2^N+1, number of property binons, Percept combination binon types, Action type and int NumBinonTypes; // the D-Habit response types - set dynamically based on SetupSense() and SetupDevice() // The names and abbreviations for the various binon types String[][] BinonTypeName = new String[68 + 1][2 + 1]; // ---- BinonTypeName$() 2nd index values // 1 int BinName; // 2 int BinAbbreviation; // The source types of property binons are 1=TextBin, 2=ContBin. There are N of these // and all other Percept combinations such as Name&Cont. // There are 2^N-1 Property plus Percept types // There is just the one Action type - a sequential combination of the // Property binons, Percept binons, response D-Habit binons and/or Action binons. // The binon types for stimuli (Percepts 15), ActBin (1) and responses (D-Habits 15) int[][] BinonTypes = new int[68 + 1][1 + 2]; // 1st index = the type of binon (dimension = NumBinonTypes) // 2nd index = binon type property // ---- BinonTypes() - 1st Index values - stimulus and response binon types // Binon type for Actions, Expectations, percepts, and action binons = NumPercepts + 1. Dynamically set int ActBin; // N=4, The number of stimulus property binon types - currently one property per sense int NumProperties; // 0, Indicates the type not set, binon will be NullObject final int NullType = 0; // ---- BinonTypes() 2nd index values // 1, Pointer points back to sense or device int SensOrDevNum; // Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator - defined above // -------------------- Percept Stimuli Perceived --------------------------------------- // the source binons for the Percepts() tree (only uses = Numsenses=NumProperties) int[] SensedBinons = new int[1 + 10]; // N=63, The number of property binons and Percept combinations of them 2^NumProperties-1 int NumPercepts; // =63 currently = (2^6)-1 would need to be (2^10) if 10 sensors int MaxPercepts; // Current and Fired Property binon and Percept IDs and XQ count int[][][] Percepts = new int[1 + 63][1 + 2][2]; // 1st index is the property / Percept binon type (dimension = NumPercepts) // 2nd index is what type of information is in the Percepts() // 3rd index is Fired=0 or Current=1 // ---- Percepts 2nd index values - type of information in Percepts() // =1, the 2nd index value for the binon ID - defined / used below int BinId; // Public XQCnt '=2, the count of times the fired binon has been recognized / fired - DEFINED ABOVE // pointers to the lower level Percepts that are used in forming this Percept int[][] PerceptSources = new int[1 + 63][1 + 3]; // ---- PerceptSources() 2nd index values // =1, the first / left source Percept binon int FirstSource; // =2, the second / right source Percept binon int SecondSource; // =3, The level in the Percept tree int PerceptLevel; // -------------------- Left and Right Targets --------------------------------------- // --- Linked List of Target Binons - for all binons ------------- // The number of Target binon entries created so far int NumTargets; // 10000 = the max number of Target binon entries possible int MaxTargets; // pointed to by Binons(ID, TriggerList) or by Binons(ID, GoalList) int[][] Targets = new int[1 + 10000][1 + 2]; // ---- Targets' 2nd index property values // 1 = The pointer to the next Targets() entry in this linked list, int NLnk; // may be a NullTarget at end of linked list // 2 = a left or right Target binon int TargetBinon; // =0, an NLnk pointer at end of linked list int NullTarget; // -------------------- D-Habit Response Produced --------------------------------------- // unused int[] RespondedBinons = new int[1 + 2]; //the response binons for the DHabits() tree (only uses = NumDevices=NumResponses) // N=15, The number of response binons and D-Habit combinations of them 2^NumDevices-1 int NumDHabits; // unused int MaxDHabits; //=15 currently = (2^4)-1 // unused int[][][] DHabits = new int[1 + 15][1 + 2][1 + 1]; //Current and Fired Property binon and Percept IDs and XQ count // 1st index is the property / Percept binon type (dimension = NumPercepts) // 2nd index is what type of information is in the Percepts() // 3rd index is Fired=0 or Current=1 // ---- Percepts 2nd index values - type of information in Percepts() // Public BinId '=1, the 2nd index value for the binon ID - defined above // Public XQCnt '=2, the count of times the fired binon has been recognized / fired - DEFINED ABOVE // -------------------- Action Stimuli Perceived --------------------------------------- // The highest level with any binons in it in STM int TopLevel; // The highest STM() entry produced / fired per cycle int HighestPerceptLvl; // =25, The highest level of complexity to which the tree can grow int MaxLevels; // STM current history of Patterns - a tree with parts at level 1 int[][][] STM = new int[25 + 1][3 + 1][25 + 1]; // 1st index is the stimulus object level // 2nd index =1 for binon type, =2 for binon ID, =3 for XQCnt, =4 for TQCnt // 3rd index = Fired = 0 for the just fired stimulus // = Current = 1 for the Current perceived stimuli // They can all be expecting a repeat or a changed / different value // = Last one whose position is the last STM entry that has something in it // ---- STM 2nd index values - type of information in STM() // Public BinId '=1, the binon ID - DEFINED ABOVE // Public XQCnt '=2, the count of times the fired binon has been recognized / fired / repeated - Defined above // =3, the count of times its trigger fired for repeat size comparison int TQCnt; // ---- STM 3rd index values - which past stimulus is it - DEFINED ABOVE // Public Fired '=0 'stimulus put in this level upon firing before being processed // Public Current '=1 'The fired one becomes the current one after processing // Move right amount to eliminate previous pattern - set in ProcessSTMLevel() int MoveAmount; // --------------------- Conscious Binons ----------------------------------------- // predicting/expecting the next binon as the goal. May have 0, 1 or more associating binons. int PerceivedBinon; // -------------------- Long Term Memory (LTM) - Monitoring Info. ------------------------- // For Display purposes only by Adapt.DUMPLTM in Adapt.LTMem // Long term memory contains a list of the stimuli that have been paid attention to. // It stores Perceptual sequences as a pair of sequential memory locations. int[][] LTMEMORY = new int[2000 + 1][8 + 1]; // 1st index is StoreAt cycle number // 2nd index is what type of information is in the LTM // ---- LTMEMORY() 2nd index values - type of information in LTMEMORY() // 1 Percept binon type int LtmPerceptTyp; // 2 Percept binon int LtmPerceptBin; // 3 Type of ES Binon - may be an S int LtmESType; // 4 ES Actbin int LtmESActBin; // 5 Type of AR Binon - may be an R int LtmARType; // 6 AR ActBin int LtmARActBin; // 7 Action binon type int LtmActionTyp; // 8 Action binon int LtmActionBin; // LTM POSITION OF LAST STIMULUS - location in LTMEMORY() - incremented by PerceptionAction() int StoreAt; // 2000 int MaxMemory; // ----------------------Input/Output History ---------------------------------------- // For display by Adapt.HISTORYDISPLAY in Adapt.IO // INPUT history - List of sense stimuli for each sense (1 to 10) String[][] INPUTS = new String[2000][10 + 1]; // OUTPUT history - List of Responses for each device (1 to 4) String[][] OUTPUTS = new String[2000][4 + 1]; // -------------------- Other Variables ------------------------------------------ // 1.2 for a 20% just noticeable difference double SizeBase; // If it is 2.0 then that is a 100% just noticeable difference double IntensityBase; // -------------------- Operational Values - Adaptron -------------------- String ASpace; // char SequentialSign = first(unicode_rightPointingTriangle()); //Chr$(16) ">" transient char SequentialSign = '>'; // "+" was Chr$(186) two vertical lines was "/" String ParallelSign; // True if create all combinations boolean CreateAll = false; // False if use only familiar parts // ********* Counters, Temporary values, Flags and Pointers ****** // ---------------------- Operational Values ------------------------------- int Normal; int Happy; int Unhappy; // Used as ActTypes for body display int PartMatch; // unused boolean PracticeMode; //Practicing the PracticeActon. Still performing it. // When finished in PracticeMode then we switch to GoalMode. // unused Public PracticeActon; //The acton that is being practiced // static Public ActiveActon; //The highest level active acton being done subconsciously // If set then this is being done subconsciously (not being practiced) // static Public DoingAct1; //The Act is being done even though it is not being practiced // This does not include the do Relax act // unused Public GoalExpected; //Goal expected by Action started - to measure success or failure // = 0 if no expectation because doing reflexive response // unused Public GoalSoFar; //Keeps track of the part of the expected goal obtained so far // unused boolean GoalMode; //Concentrating on the goal of the action being practiced. // We have finished the acton execution. // If set it will cause directed attention to the GoalExpected // unused Public ExpectedGoal; //Goal expected for thinking about // unused Public TraceGoal; //Used for Trace - The goal we are either trying to achieve or avoid // unused Public MATCHUSE; //Trigger match Action in Actons() that is interesting to do // unused Public ActionDesire; //Interest in the MATCHUSE entry for AttendTo // unused Public PartialMATCHUSE; //same as MATCHUSE but for partial matches // unused Public PartialActionDesire; // unused Public PartialTrigger; //set to the partial trigger object if partial trigger true // unused boolean ThoughtUsed; // set true if last response was reactive / reflex boolean DoingReaction = false; // set true if repeating a known response as a reflexive reaction boolean DoingRepeat = false; // Last reflexive response used from Acts list int LastAct; // unused Public NextAct; //The next output act for reflexive response from Acts() // unused Public ResponseOutput; //The one output in this cycle for storing in LTM trace // unused Public Recency; // unused boolean PracticeIt; //Global because used in Trace() // unused boolean DoIt; //Global because used in Trace() // unused boolean React; //Global because used in Trace() // Count of how many stimuli have been input/output in INPUTS$() and OUTPUTS$() int LIN; // unused boolean FreezeSList; //When true don't do the DUMPSTIMS any more // Count of inputs for display of history int COUNTIN; // The list of recent .WLD files created - kept in RecentWldList.TXT String[] RecentWorld = new String[4]; // The list of recent .BDY files created - kept in RecentBdyList.TXT String[] RecentBody = new String[4]; // Either, Running World or just Started int OperatingMode; int Running; int Started; // ********* Counters, Temporary values, Flags and Pointers ****** // unused Public I, J, T, M, H, N, K, P, F, S, Hab; // unused Public ThoughtDesire; char vbDblQuote; // --------------- Colours -------------- int Black; int White; int LightBlue; int DarkBlue; // End of (Declarations) public void Initialize_Adaptron() { // Called only once from World form when it loads, World.Form_Load() // Initialize all values that don't change FourWay = chr(170); // The initial / default Body name Smarty0 = "Smarty0"; // sets the inital values in BodySetting$() InitBodySettingsToSmarty0(); // -------------------------- Senses and Sensors -------------------------- // max no. of physical senses possible in Values$ arrays MaxSenses = 10; // Flag for Senses versus Devices IsSense = 1; // ---- Senses() and Devices() - 2nd index values - Sense and device Properties // Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin PropertyBinonType = 1; // Symbolic or Magnitude indicator SymbolicOrMagnitude = 2; // Lower limit of range of values, zero is minimum (65 = "A") LowerRangeLimit = 3; // Upper limit of range of values, 255 is maximum (90 ="Z") UpperRangeLimit = 4; // Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360) LinearOrCircular = 5; // Integer Values or Log Values, Temperatures are Integers while Decibels are Logs IntegersOrLogs = 6; // Number of sensors in sensor array NumberOfSensors = 7; // Are sensors adjacent (dependent) or independent SensorsDependentOrIndependent = 8; // Indicates that the values from this sense are symbolic, range A -> Z Symbolic = 1; // Indicates that the values from this sense are numeric, integers, range 0 -> Limit Magnitude = 2; // Indicates that the values go from the lower limit to upper limit Linear = 1; // Indicates that the values rap around from the upper limit to 0 Circular = 2; // Indicates that the values are integer readings IntegerValues = 1; // Indicates that the values are already logs - orders of magnitude LogValues = 2; // Sensors in array are beside each other (adjacent) Dependent = 1; // Sensors are not associated with each other Independent = 2; // -------------------- Values of stimuli from senses / sensors ------------------------------ // ---- SensorValues 2nd index values - type of information in SensorValues() // the value for the stimulus, if symbolic then value = Asc(Symbol$) Valu = 1; // the count of times the value has repeated, also used below XQCnt = 2; // The character used when no letter provided for the IDL value of a TextBin binon NoName = "_"; // a # for internal use to indicate a block at the location ABlock = "#"; // ---- SensorValues 3rd index values - which past stimulus it is - also used below // stimulus put in this level upon firing before being processed Fired = 0; // The Fired one becomes the Current one after processing Current = 1; // -------------------- Devices ------------------------------------------------ // Maximum number of devices = max 4 devices MaxDevices = 4; // Flag for Devices versus Senses IsDevice = 2; // "z" indicates Smarty does not have this move ability NoMoveOrTurn = "z"; // rotate right, left and around 180 degrees WheelMovement = "-flrb" + TurnRght + TurnLft + TurnArnd; // "-" to indicate there was no motion in the Motion$ stimulus value NoMove = WheelMovement.substring(0, 1); // -------------------- The Stimulus Objects (Binons) ------------------------- // Max number of binons per type MaxBinons = 5000; // with 2 senses and 1 device this is =5 MaxBinonTypes = 68; // ---- BinonTypeName$() 2nd index values BinName = 1; BinAbbreviation = 2; // ---- BinonTypes() 2nd index values // Pointer points back to sense or device SensOrDevNum = 1; // SymbolicOrMagnitude = 2 ' Symbolic or Magnitude indicator - initialized above // -------------------- Percept Stimuli Perceived --------------------------------------- // currently based on maxsenses=5 senses=number of property types MaxPercepts = 63; // ---- Percepts() 2nd index values - type of information in Percepts() // the 2nd index value for the binon ID - defined / used below BinId = 1; // XQCnt = 2 ' the count of times the fired binon has been recognized / fired - DEFINED ABOVE // ---- PerceptSources() 2nd index values // the first / left source Percept binon FirstSource = 1; // the second / right source Percept binon SecondSource = 2; // The level in the Percept tree PerceptLevel = 3; // ---- Binons() Properties - 2nd index values // The type of binon BType = 1; // Left source binon pointer O1 = 2; // the count of times the trigger has fired TQ = 3; // Right source binon pointer O2 = 4; // the number of times the goal has fired GQ = 5; // The ratio value of the binon IDL = 6; // Interest Value (NOVEL, INTERESTING, or Familiar) IntVl = 7; // Level of object = number of lowest level parts involved OLv = 8; // Sequential or Parallel property SP = 9; // points to the linked list of right target binons [Targets()] TriggerList = 10; // Count of its sequential right targets, >1 means it has more than one goal TriggerCount = 11; // points to the linked list of left target binons [Targets()] GoalList = 12; // Count of its sequential left targets, >1 means can not predict its trigger GoalCount = 13; // Action (Stimulus - Response) or Attention (Response - Stimulus) level 1 Sequential binon AE = 14; // Indicates the O1 or O2 pointer is not pointing to another binon NullObject = -1; // Interest not known yet NoInterest = -1; // 2 or 3 - number of interest levels, 2= Novel and Familiar, 3= Novel, Interesting, and Familiar InterestLevels = 2; // ---- Sequential or Parallel property values for Binons(x, SP) Sequential = -1; Parallel = 1; // ---- Action or Attention property values for Binons(x, AE) Action = 1; Attention = 2; // --- Linked List of Target Binons - for Percepts and Actions ------------- // = the max number of Target binon entries possible MaxTargets = 10000; // ---- Targets' 2nd index property values // = The pointer to the next Targets() entry in this linked list, NLnk = 1; // = a left or right Target binon TargetBinon = 2; // an NLnk pointer at end of linked list NullTarget = 0; // -------------------- Stimuli Perceived STM() --------------------------------------- // The highest level of complexity to which the tree can grow MaxLevels = 25; // ---- STM 2nd index values - type of information in STM() // BinId = 1 ' the binon ID - initialized above // XQCnt = 2 ' the count of times the fired binon has been recognized / fired / repeated - initialized above // the count of times its trigger fired for repeat size comparison TQCnt = 3; // -------------------- Long Term Memory (LTM) - Monitoring Info. ------------------------- LtmPerceptTyp = 1; LtmPerceptBin = 2; LtmESType = 3; LtmESActBin = 4; LtmARType = 5; LtmARActBin = 6; LtmActionTyp = 7; LtmActionBin = 8; MaxMemory = 2000; // ---------------------- Operational Values ------------------------------- ASpace = " "; // Was Chr$(186), 'was "/" ParallelSign = "+"; // Used as ActTypes for body display Normal = 0; Happy = 1; PartMatch = 2; Unhappy = 3; // = " vbDblQuote = (char) 34; Running = 2; Started = 1; // Just started so WorldHelp is displayed OperatingMode = Started; Black = 0x0; White = 0xFFFFFF; LightBlue = 0xFF8080; DarkBlue = 0xC00000; // persist changes change(); } private static String chr(int c) { return String.valueOf((char) c); } public final void GetTypeInfo(int BinTyp, ISetter BinonTyp, ISetter Rdgs) { // Returns the names of the BinonTyp$ and Rdg$ for the given BinTyp // Public BinonTypeName$(1 To 5, 1 To 2) 'The names and abbreviations for the various binon types // '---- BinonTypeName$() 2nd index values // Public BinName '1 // Public BinAbbreviation '2 Rdgs.set(""); BinonTyp.set(""); if (BinTyp == NullType) { BinonTyp.set("Null"); Rdgs.set("~ = "); } else { BinonTyp.set(BinonTypeName[BinTyp][BinName]); Rdgs.set(BinonTypeName[BinTyp][BinAbbreviation] + "= "); } } // End of GetTypeInfo() public final int BinonTypeOf(int TheBinon) { int tempBinonTypeOf; if (TheBinon == NullObject) { tempBinonTypeOf = NullType; } else { tempBinonTypeOf = Binons[TheBinon][BType]; } return tempBinonTypeOf; } // End of BinonTypeOf() public final void GetValue(int OOO, Var v) { // Returns the value for the object based on its Type int Readng; int TheBinon; int LeftBinon; // Recursive routine to add values to V$ for any binon/object if (OOO == NullObject) { return; } // VB TO JAVA CONVERTER NOTE: The following VB 'Select Case' included either a non-ordinal switch expression or non-ordinal, range-type, or non-constant 'Case' expressions and was converted to Java 'if-else' logic: // Select Case BinonTypeOf(OOO) var tempVar = BinonTypeOf(OOO); // ORIGINAL LINE: Case ActBin //Public ActBin = sequential - action = NumPercepts+1 if (// Public ActBin = sequential - action = NumPercepts+1 tempVar == ActBin) { TheBinon = OOO; while (// While we have an Action BinonTypeOf(TheBinon) == ActBin) { ping(); LeftBinon = TheBinon; // Go down the left side to the bottom Property or Percept binon while (// While we have an Action BinonTypeOf(LeftBinon) == ActBin) { ping(); // Get the left source part LeftBinon = Binons[LeftBinon][O1]; } // get the property and/or Percept binon GetValue(LeftBinon, v); v.set(v.get() + SequentialSign); // Go to the right side and repeat going down its left side TheBinon = Binons[TheBinon][O2]; } // get the last Property or Percept binon on the right side GetValue(TheBinon, v); } else // ORIGINAL LINE: Case 1 To NumProperties //Senses / property binon if (// Senses / property binon tempVar >= 1 && tempVar <= NumProperties) { // The binons value Readng = Binons[OOO][IDL]; if (BinonTypes[BinonTypeOf(OOO)][SymbolicOrMagnitude] == Symbolic) { if (Readng < 32) { v.set(v.get() + "~"); } else { // text v.set(v.get() + chr(Readng)); } } else // Else the property is Magnitude { // a number v.set(v.get() + vbToStr(Readng)); } } else // ORIGINAL LINE: Case NumProperties + 1 To NumPercepts //Percept binons if (// Percept binons tempVar >= NumProperties + 1 && tempVar <= NumPercepts) { TheBinon = OOO; while (// While we have a Percept BinonTypeOf(TheBinon) > NumProperties) { ping(); LeftBinon = TheBinon; // Go down the left side to the bottom property binon while (// While we have a Percept BinonTypeOf(LeftBinon) > NumProperties) { ping(); // Get the left source part LeftBinon = Binons[LeftBinon][O1]; } // get the property binon GetValue(LeftBinon, v); v.set(v.get() + ParallelSign); // Go to the right side and repeat going down its left side TheBinon = Binons[TheBinon][O2]; } // get the last Property binon on the right side GetValue(TheBinon, v); } else // ORIGINAL LINE: Case ActBin + 1 To NumBinonTypes //A response / device binon if (// A response / device binon tempVar >= ActBin + 1 && tempVar <= NumBinonTypes) { Readng = Binons[OOO][IDL]; if (Readng < 32) { v.set(v.get() + "~"); } else { // symbolic v.set(v.get() + chr(Readng)); } } } // End of GetValue() public final void RememberResponse(int RespBin, int StoreAtPlace) { // Save the last response for LTM display // Public LTMEMORY&(1 To 2000, 1 To 6) -- comment stefan: not really - it's going to 8 // '1st index is StoreAt cycle number // '2nd index is what type of information is in the LTM // // '---- LTMEMORY() 2nd index values - type of information in LTMEMORY() // Public LtmPerceptTyp '1 Percept binon type // Public LtmPerceptBin '2 Percept binon // Public LtmESType '3 Type of ES Binon - may be an S // Public LtmESActBin '4 ES Actbin // Public LtmARType '5 Type of AR Binon - may be an R // Public LtmARActBin '6 AR ActBin // Public LtmActionTyp '7 Action binon type // Public LtmActionBin '8 Action binon LTMEMORY[StoreAtPlace][LtmActionTyp] = BinonTypeOf(RespBin); LTMEMORY[StoreAtPlace][LtmActionBin] = RespBin; } // End of RememberResponse() public final void RememberStimulus(int TrigObj, int StoreAtPlace) { // Save the given relationship / association in LTM for display // Public LTMEMORY&(1 To 2000, 1 To 6) // '1st index is StoreAt cycle number // '2nd index is what type of information is in the LTM // // '---- LTMEMORY() 2nd index values - type of information in LTMEMORY() // Public LtmPerceptTyp '1 Percept binon type // Public LtmPerceptBin '2 Percept binon // Public LtmESType '3 Type of ES Binon - may be an S // Public LtmESActBin '4 ES Actbin // Public LtmARType '5 Type of AR Binon - may be an R // Public LtmARActBin '6 AR ActBin // Public LtmActionTyp '7 Action binon type // Public LtmActionBin '8 Action binon LTMEMORY[StoreAtPlace][LtmPerceptTyp] = BinonTypeOf(TrigObj); LTMEMORY[StoreAtPlace][LtmPerceptBin] = TrigObj; } // End of RememberStimulus() public final void SetupSense(int SenseNum, String Sense_Name, String BinonName, String BinonAbbrev, int MagnOrSymb, int LowerLimit, int UpperLimit, String Stimuli, int LinOrCirc, int IntOrLog, int NumSensrs, int SensorDependency) { printVars_str("SetupSense", "SenseNum", SenseNum, "Sense_Name", Sense_Name, "NumSensrs", NumSensrs); // If the SenseNum passed in is zero this routine returns the Sense number (SenseNum) // for the given Sense, else it modifies the given SenseNum // The range or number of sensors is NumSensrs - max 256 // IntensityRange: is the range or number of intensity values for the sensors // Stimuli$: is a string of possible stimuli for this sensor - saved in SensorStimuli$() // Sense_Name$: is the name of the sense // MagnOrSymb: = Magnitude if each sensor measures a Magnitude range of intensity // = Symbolic if each sensor provides readings that are symbolic. // LinOrCirc: = Linear // = Circular // unused String Ssr = null; int UseSense; // unused String SG = null; int Sns; var BinTypNum = new Var<>(0); String DisplayStimuli; // Public NumSenses 'The number of physical senses, Max of 8 // 'Currently equals the NumProperties since each sense currently = 1 property type // Public MaxSenses 'Maximum number of senses = max 8 physical senses // Public Sense$(1 To 8) 'Names of senses, up to 8 physical senses // // Public Senses[1 To 8][1 To 6] 'Properties of the different senses // '1st index = Sense number // '2nd index = Sense property // Public SensorStimuli$(1 To 10) 'A string of the possible symbolic stimuli for the sensor // // '---- Senses() - 2nd index values - Sense Properties // Public PropertyBinonType '1, Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin // Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator // Public LowerRangeLimit '3, Lower limit of range of values, zero is minimum (65 = "A") // Public UpperRangeLimit '4, Upper limit of range of values, 255 is maximum (90 ="Z") // Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360) // Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs // Public NumberOfSensors '7 Number of sensors in sensor array // Public SensorsDependentOrIndependent '8 are sensors adjacent (dependent) or independent // // Public Symbolic '1, Indicates that the values from this sense are symbolic, range A -> Z // Public Magnitude '2, Indicates that the values from this sense are numeric, integers, range 0 -> Limit // // Public Linear '1, Indicates that the values go from the lower limit to upper limit // Public Circular '2, Indicates that the values rap around from the upper limit to 0 // // Public IntegerValues '1, Indicates that the values are integer readings // Public LogValues '2, Indicates that the values are already logs - orders of magnitude // if (// Can't assign another new sense number NumSenses == MaxSenses) { Stop(); } // There are only so many senses in SensorValues array // currently set to 8 in Adaptron.Initialize_Adaptron() if (// don't have a sense number yet so assign and return it SenseNum == 0) { // The new sense number for this sense NumSenses = NumSenses + 1; // The returned sense number SenseNum = NumSenses; } else if (// else it is more than allowed SenseNum > MaxSenses) { Stop(); } else if (// else is it higher than the next one available SenseNum > NumSenses + 1) { Stop(); } else if (// else use the one passed in - overriding an existing sense SenseNum <= NumSenses) { } else if (// else is it equal to the next one available SenseNum == NumSenses + 1) { // which equals NumSenses + 1 NumSenses = SenseNum; } UseSense = SenseNum; if (// only 8 sensors allowed per sense for now - maybe only NumSensrs > 8) { Stop(); } // need this limit if independent sensors if (// only 256 values allowed for intensity IntensityRange > 256) { Stop(); } Sense[UseSense] = Sense_Name; Senses[UseSense][SymbolicOrMagnitude] = MagnOrSymb; Senses[UseSense][LowerRangeLimit] = LowerLimit; Senses[UseSense][UpperRangeLimit] = UpperLimit; // If not "" these take preference over the upper and lower limit SensorStimuli[UseSense] = Stimuli; if (// Magnitude READINGS Senses[UseSense][SymbolicOrMagnitude] == Magnitude) { // can be circular or linear Senses[UseSense][LinearOrCircular] = LinOrCirc; // can not have symbolic list SensorStimuli[UseSense] = ""; } else // Symbolic readings can not be circular { // non circular Senses[UseSense][LinearOrCircular] = Linear; } Senses[UseSense][IntegersOrLogs] = IntOrLog; Senses[UseSense][NumberOfSensors] = NumSensrs; Senses[UseSense][SensorsDependentOrIndependent] = SensorDependency; // SetupBinonTypes(SenseOrDeviceNum, BinNam$, BinAbb$, IsASense, BinonTypReturned) SetupBinonTypes(UseSense, BinonName, BinonAbbrev, IsSense, BinTypNum); // Currently BinonType = Sense = property binon Senses[UseSense][PropertyBinonType] = BinTypNum.get(); // and fill in sense info on world page StringBuilder sensorInfo = new StringBuilder(); for (Sns = 1; Sns <= NumSenses; Sns++) { ping(); if (Senses[Sns][SymbolicOrMagnitude] == Magnitude) { DisplayStimuli = StringHelper.trim(String.valueOf(Senses[Sns][LowerRangeLimit]), ' ') + " to" + Senses[Sns][UpperRangeLimit]; } else // symbolic values { if (// If no symbolic list then use upper and lower limit SensorStimuli[Sns].equals("")) { DisplayStimuli = chr(Senses[Sns][LowerRangeLimit]) + " to " + chr(Senses[Sns][UpperRangeLimit]); } else { DisplayStimuli = SensorStimuli[Sns]; DisplayStimuli = replace(DisplayStimuli, NoMoveOrTurn, ASpace); } } sensorInfo.append(takeFirst(8, Sense[Sns] + ": ") + " " + DisplayStimuli + " " + SymbOrMagn(IsSense, Sns) + "\r\n"); } World.showSensorValues(str(sensorInfo)); } // End of SetupSense() private static void Stop() { Stop("STOP"); } private static void Stop(String msg) { throw new RuntimeException(msg); } public final // Called from DesignBody.UseThisBody_Click() void SetupVision() { int VisionSense; int MS = 0; // renamed because of clash with JavaX's LL int ll = 0; int UL = 0; // BodySetting$(7) = VisionConfig.VisionDown // BodySetting$(8) = VisionConfig.VisionLeft // BodySetting$(9) = VisionConfig.VisionRight // BodySetting$(10) = VisionConfig.VisionInFront // BodySetting$(11) = VisionConfig.VisionBehind // BodySetting$(12) = VisionConfig.VisionSymbolicOrMagnitude(0) // BodySetting$(13) = VisionConfig.VisionSymbolicOrMagnitude(1) // BodySetting$(21) = VisionConfig.VisionSymbolicOrMagnitude(2) // so a new sense number assigned automatically by SetupSense() VisionSense = 0; // Body 1 'Sense #1 looks down at square, Device #1 moves Left, Right, Up, Down // 'set up Sense #1, 1 sensor // 'SetupSense(SenseNum, Sense_Name$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _ // LinOrCirc, IntOrLog, NumSensrs, SensorDependency) // Call SetupSense(InputSense, "Input", "Text", "Tx", Symbolic, 65, 122, Linear, IntegerValues, 1, Independent) // // 'SetupDevice(DeviceNum, DName$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _ // Responses$, LinOrCirc, IntOrLog) // Call SetupDevice(DevNum, "Output", "Letter", "Lt", Symbolic, 97, 100, "", Linear, IntegerValues) // // Body 2 'Looks forward at next cell, Turns left, right & moves forward // 'set up Sense #1, 1 Sensor // Call SetupSense(InputSense, "Input", "Text", "Tx", Symbolic, 65, 113, Linear, IntegerValues, 1, Independent) // Call SetupDevice(DevNum, "Output", "Letter", "Lt", Symbolic, 97, 99, "", Linear, IntegerValues) if (// radio button VisionSymbolicOrMagnitude(0) selected isTrue(BodySetting[12])) { MS = Symbolic; // "A" 1st cell location ll = 65; // "z" last possible cell location - actually if 8 x 8 then it is Chr$(129) UL = 122; } if (// radio button VisionSymbolicOrMagnitude(1) selected isTrue(BodySetting[13])) { MS = Magnitude; ll = 1; // max 8 cells in any direction UL = 8; } if (// radio button VisionSymbolicOrMagnitude(2) selected isTrue(BodySetting[21])) { MS = Symbolic; // Wall$ = Chr$(20) Terminal font ll = asc(Wall); // empty square beside it UL = asc(EmptySquare); } if (// Looking down box is checked eq(BodySetting[7], "1")) { // SetupSense(SenseNum, Sense_Name$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _ // Stimuli, LinOrCirc, IntOrLog, NumSensrs, SensorDependency); SetupSense(VisionSense, "VisionD", "VisionD", "VD", MS, ll, UL, "", Linear, IntegerValues, 1, Independent); } VisionSense = 0; if (// Looking left box is checked eq(BodySetting[8], "1")) { SetupSense(VisionSense, "VisionL", "VisionL", "Vl", MS, ll, UL, "", Linear, IntegerValues, 1, Independent); } VisionSense = 0; if (// Looking right box is checked eq(BodySetting[9], "1")) { SetupSense(VisionSense, "VisionR", "VisionR", "Vr", MS, ll, UL, "", Linear, IntegerValues, 1, Independent); } VisionSense = 0; if (// Looking InFront box is checked eq(BodySetting[10], "1")) { SetupSense(VisionSense, "VisionF", "VisionF", "Vf", MS, ll, UL, "", Linear, IntegerValues, 1, Independent); } VisionSense = 0; if (// Looking Behind box is checked eq(BodySetting[11], "1")) { SetupSense(VisionSense, "VisionB", "VisionB", "Vb", MS, ll, UL, "", Linear, IntegerValues, 1, Independent); } } // End of SetupVision() private int asc(String s) { return empty(s) ? 0 : s.charAt(0); } private boolean isTrue(String s) { return "True".equals(s); } public final void SetupTouch() { } // End of SetupTouch() public final void SetupWheels() { int WheelsDevice; int MS; // unused String LL = null; // unused String UL = null; StringBuilder WheelResponses; int MotionSense; // BodySetting$(14) = WheelsConfig.MoveForward // BodySetting$(15) = WheelsConfig.MoveLeft // BodySetting$(16) = WheelsConfig.MoveRight // BodySetting$(17) = WheelsConfig.MoveBackward // BodySetting$(18) = WheelsConfig.TurnRight // BodySetting$(19) = WheelsConfig.TurnLeft // BodySetting$(20) = WheelsConfig.TurnAround // BodySetting$(4) = WheelsConfig.AddAWheelSensor // Body 1 'Sense #1 looks down at square, Device #1 moves Left, Right, Up, Down // 'set up Sense #1, 1 sensor // 'SetupSense(SenseNum, Sense_Name$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _ // LinOrCirc, IntOrLog, NumSensrs, SensorDependency) // Call SetupSense(InputSense, "Input", "Text", "Tx", Symbolic, 65, 113, Linear, IntegerValues, 1, Independent) // // Call SetupDevice(DevNum, "Output", "Letter", "Lt", Symbolic, 97, 100, "", Linear, IntegerValues) // // Body 2 'Looks forward at next cell, Turns left, right & moves forward // 'set up Sense #1, 1 Sensor // Call SetupSense(InputSense, "Input", "Text", "Tx", Symbolic, 65, 113, Linear, IntegerValues, 1, Independent) // Call SetupDevice(DevNum, "Output", "Letter", "Lt", Symbolic, 97, 99, "", Linear, IntegerValues) // The device number assigned to the device by SetupDevice() WheelsDevice = 0; MS = Symbolic; // will be filled in with move symbols "-flrb" and turn symbols, WheelResponses = new StringBuilder("-"); // a "z" for an invalid movement, the "-" for do nothing // Assume no turning capability, display Smarty as Happy face WheelsTurn = false; if (MS == Symbolic) { for (var I = 14; I <= 20; I++) { ping(); if (// if it is checked then eq(BodySetting[I], "1")) { switch(I) { case // Forward 14: WheelResponses.append(MoveForward); break; case // Left 15: WheelResponses.append(MoveToLeft); break; case // Right 16: WheelResponses.append(MoveToRight); break; case // Backward 17: WheelResponses.append(MoveBackward); break; case // Turn right 90 degrees 18: // right angle symbol WheelResponses.append(TurnRght); WheelsTurn = true; break; case // Turn left 90 degrees 19: // left angle symbol WheelResponses.append(TurnLft); WheelsTurn = true; break; case // Turn around 180 degrees 20: // double arrow symbol WheelResponses.append(TurnArnd); WheelsTurn = true; break; } } else { WheelResponses.append(NoMoveOrTurn); } } } // the same movements should be recognizable WheelMovement = WheelResponses.toString(); // Setup a motion sense if WheelsConfig.AddAWheelSensor = 1 is checked if (eq(BodySetting[4], "1")) { MotionSense = 0; // SetupSense(SenseNum, Sense_Name$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _ // Stimuli, LinOrCirc, IntOrLog, NumSensrs, SensorDependency); SetupSense(MotionSense, "Motion", "Motion", "Mo", Symbolic, 1, 1, WheelMovement, Linear, IntegerValues, 1, Independent); } // SetupDevice(DeviceNum, DName$, BinonName$, BinonAbbrev$, MagnOrSymb, LowerLimit, UpperLimit, _ // Responses, LinOrCirc, IntOrLog); SetupDevice(WheelsDevice, "Wheels", "Wheels", "Wh", MS, 1, 1, WheelResponses.toString(), Linear, IntegerValues); } // End of SetupWheels() public final void SetupArms() { } // End of SetupArms() public // Initialize the BodySetting$() or BodyValue$() to Smarty0 values void InitBodyToSmarty0(// Initialize the BodySetting$() or BodyValue$() to Smarty0 values String[] Body) { // Count of Body$() values Body[0] = "21"; Body[1] = Smarty0; // Vision.Value = 1 - checked Body[2] = "1"; // Touch.Value Body[3] = "0"; // WheelsConfig.AddAWheelSensor Body[4] = "0"; // Wheels.Value Body[5] = "1"; // Arms.Value Body[6] = "0"; // VisionConfig.VisionDown Body[7] = "1"; // VisionConfig.VisionLeft Body[8] = "0"; // VisionConfig.VisionRight Body[9] = "0"; // VisionConfig.VisionInFront Body[10] = "0"; // VisionConfig.VisionBehind Body[11] = "0"; // VisionConfig.VisionSymbolicOrMagnitude(0) Body[12] = "True"; // VisionConfig.VisionSymbolicOrMagnitude(1) Body[13] = "False"; // WheelsConfig.MoveForward Body[14] = "1"; // WheelsConfig.MoveLeft Body[15] = "1"; // WheelsConfig.MoveRight Body[16] = "1"; // WheelsConfig.MoveBackward Body[17] = "1"; // WheelsConfig.TurnRight Body[18] = "0"; // WheelsConfig.TurnLeft Body[19] = "0"; // WheelsConfig.TurnAround Body[20] = "0"; // VisionConfig.VisionSymbolicOrMagnitude(2) Body[21] = "False"; } // End of InitBodyToSmarty0() public void InitBodySettingsToSmarty0() { InitBodyToSmarty0(BodySetting); } public final void InitBodyValuesToSmarty0() { InitBodyToSmarty0(BodyValue); } public final String SymbOrMagn(int SensOrDevc, int SensOrDevcNumber) { String tempSymbOrMagn; // called from SetupSense() & SetupDevice() int SorG; if (SensOrDevc == IsSense) { SorG = Senses[SensOrDevcNumber][SymbolicOrMagnitude]; } else // Else SensOrDevc = IsDevice { SorG = Devices[SensOrDevcNumber][SymbolicOrMagnitude]; } if (SorG == Symbolic) { tempSymbOrMagn = "Symbolic"; } else { tempSymbOrMagn = "Magnitude"; } return tempSymbOrMagn; } // End of SymbOrMagn$() public final void SetupBinonTypes(int SenseOrDeviceNum, String BinNam, String BinAbb, int IsASense, Var BinonTypReturned) { // Called by SetUpSense() and SetupDevice() // After setting up a sense or device the binontypes() information must be updated correctly // SenseOrDeviceNum could be one that already exists and is being reset int BinTypNum = 0; int PerceptBinTyp; int DHabitBinTyp; int FirstPtr; int SecondPtr; int ThisPercept; int StartPercept; int EndPercept; int ThisLevel; // '---- Binons[x][BType] - stimulus and response binon types // TextBin = 1 ' = A letter (symbolic) // ContBin = 2 ' = Contrast pattern - intensity (Magnitude) // 'Parallel combinations should be put in the binons above the property type ones. // NCBin = 3 ' = TextBin & ContBin combination // ActBin = 4 ' = 2^N = NumPercepts+1, holds sequential binons. // LetrBin = 5 ' = Response binon = letters // ------------------ Property and Percept combinations -------------------------- // The number of combinations at each level of complexity when combining independent senses. // # of Sensors // or Senses // Stimuli @ P-Level 1 2 3 4 5 6 7 8 Total // 1 1 1 // 2 2 1 3 // 3 3 3 1 7 // 4 4 6 4 1 15 // 5 5 10 10 5 1 31 // 6 6 15 20 15 6 1 63 // 7 7 21 35 35 21 7 1 127 // 8 8 28 56 70 56 28 8 1 255 // N 2^N - 1 // Public NumProperties 'N=2, The number of stimulus property binon types // Public NumPercepts 'N=3, The number of property binons and Percept combinations of them // Public NumBinonTypes '= 2^N+1, number of property binons, Percept combination binon types, Action type and // ' the response type // Public MaxBinonTypes 'with 2 senses and 1 device this is =5 // Public BinonTypeName$(1 To 31, 1 To 2) 'The names and abbreviations for the various binon types // '---- BinonTypeName$() 2nd index values // Public BinName '1 // Public BinAbbreviation '2 // 'The source types of property binons are 1=TextBin, 2=ContBin. There are N of these // 'and all other Percept combinations such as Name&Cont. // 'There are 2^N-1 Property plus Percept types // 'There is just the one Action type - a sequential combination of the // 'Property binons, Percept binons, response binon and/or Action binons. // 'Added responses as LetrBin binons so NumBinonTypes = 2^N + 1 // Public BinonTypes[1 To 31][1 To 4] 'The binon types for stimuli, ActBin and responses // '1st index = the type of binon (dimension = NumBinonTypes) // '2nd index = binon type property // // ---- BinonTypes() 2nd index values // Public SensOrDevNum '1, Pointer points back to sense or device // Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator if (// If setting up a sense then IsASense == IsSense) { if (// if it is an existing sense then resetting it SenseOrDeviceNum <= NumProperties) { BinTypNum = SenseOrDeviceNum; } else if (// else if it is the next new sense then SenseOrDeviceNum == NumProperties + 1) { // N=2, The number of stimulus property binon types NumProperties = SenseOrDeviceNum; BinTypNum = NumProperties; // N=3, The number of property binons and Percept combinations of them NumPercepts = (2 << (NumProperties - 1)) - 1; for (PerceptBinTyp = NumProperties + 1; PerceptBinTyp <= NumPercepts; PerceptBinTyp++) { ping(); BinonTypeName[PerceptBinTyp][BinName] = "Percept"; BinonTypeName[PerceptBinTyp][BinAbbreviation] = "Pc"; } // Setup the PerceptSources() to point at the correct source entries at the level below // Filling in level 2 Percept information ThisLevel = 2; // Position of 1st Percept combination of sense/property binons ThisPercept = NumProperties + 1; // Start of range of pairs - level-2 Percepts, level-1 Percepts=property binons StartPercept = ThisPercept; for (// Create all the 2nd level pair pointers FirstPtr = 1; // Create all the 2nd level pair pointers FirstPtr < NumProperties; // Create all the 2nd level pair pointers FirstPtr++) { ping(); for (SecondPtr = FirstPtr + 1; SecondPtr <= NumProperties; SecondPtr++) { ping(); PerceptSources[ThisPercept][FirstSource] = FirstPtr; PerceptSources[ThisPercept][SecondSource] = SecondPtr; PerceptSources[ThisPercept][PerceptLevel] = ThisLevel; // Next combination Percept will go in here ThisPercept = ThisPercept + 1; } } // End of range of level-2 Percepts - pairs of property binons EndPercept = ThisPercept - 1; // Setup the level-3+ PerceptSources() while (EndPercept - StartPercept > 0) { ping(); // populate next level up ThisLevel = ThisLevel + 1; for (FirstPtr = StartPercept; FirstPtr < EndPercept; FirstPtr++) { ping(); for (SecondPtr = FirstPtr + 1; SecondPtr <= EndPercept; SecondPtr++) { ping(); if (// if share a common sub Percept PerceptSources[FirstPtr][SecondSource] == PerceptSources[SecondPtr][FirstSource]) { PerceptSources[ThisPercept][FirstSource] = FirstPtr; PerceptSources[ThisPercept][SecondSource] = SecondPtr; PerceptSources[ThisPercept][PerceptLevel] = ThisLevel; // Next combination Percept will go in here ThisPercept = ThisPercept + 1; } } } // Start next range after end of previous range StartPercept = EndPercept + 1; // End of range of this level Percepts EndPercept = ThisPercept - 1; } // ActBin holds action and expectation binons = 2^N = NumPercepts + 1 ActBin = NumPercepts + 1; BinonTypeName[ActBin][BinName] = "Action"; BinonTypeName[ActBin][BinAbbreviation] = "Ac"; // The number of types so far = 2^N NumBinonTypes = ActBin; } else { // no other value allowed Stop(); } } else // Else setting up a device { if (// If it is an existing device then restting it SenseOrDeviceNum + ActBin <= NumBinonTypes) { BinTypNum = SenseOrDeviceNum; } else if (// else if it is the next new device number then SenseOrDeviceNum + ActBin == NumBinonTypes + 1) { // = 2^N+x, number of property binons, Percept combination binon types, NumBinonTypes = NumBinonTypes + 1; BinTypNum = NumBinonTypes; // N=3, The number of device response binons and D-Habit combinations of them NumDHabits = (2 << (SenseOrDeviceNum - 1)) - 1; // VB TO JAVA CONVERTER NOTE: The ending condition of VB 'For' loops is tested only on entry to the loop. VB to Java Converter has created a temporary variable in order to use the initial value of ActBin + NumDHabits for every iteration: var tempVar = ActBin + NumDHabits; for (DHabitBinTyp = ActBin + 1 + SenseOrDeviceNum; DHabitBinTyp <= tempVar; DHabitBinTyp++) { ping(); BinonTypeName[DHabitBinTyp][BinName] = "D-Habit"; BinonTypeName[DHabitBinTyp][BinAbbreviation] = "DH"; } NumBinonTypes = ActBin + NumDHabits; } else { // no other value allowed Stop(); } } BinonTypeName[BinTypNum][BinName] = BinNam; BinonTypeName[BinTypNum][BinAbbreviation] = BinAbb; // points back to the device number BinonTypes[BinTypNum][SensOrDevNum] = SenseOrDeviceNum; BinonTypes[BinTypNum][SymbolicOrMagnitude] = Senses[SenseOrDeviceNum][SymbolicOrMagnitude]; BinonTypReturned.set(BinTypNum); } // End of SetupBinonTypes() public final void SetupDevice(int DeviceNum, String DName, String BinonName, String BinonAbbrev, int MagnOrSymb, int LowerLimit, int UpperLimit, String Responses, int LinOrCirc, int IntOrLog) { // This routine returns the Device number (DeviceNum) for the given Device type if none is provided // DName$: is the name of the device type // IntensityRange: is the range or number of response values for the device if it takes magnitude values // Responses$: is a string of characters representing the possible movements // BinonType: The response binon type int UseDevice; var BinTypNum = new Var<>(0); String DisplayResponses; // -------------------- Devices ------------------------------------------------ // Public NumDevices 'Number of output devices // Public MaxDevices 'Maximum number of devices = max 8 devices // Public Device$(1 To 8) 'Names of device, up to 8 devices // // Public Devices[1 To 8][1 To 5] 'Properties of the output / response devices // '1st index = Device number // '2nd index = Device property // Public DeviceResponses$(1 To 4) 'A string of the possible symbolic responses for the devices // ---- Devices() - 2nd index values - Device Properties - DEFINED ABOVE // Public PropertyBinonType '1, Response property binon type e.g. 1 = LetrBin // Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator // Public LowerRangeLimit '3, Lower limit of range of response values, zero is minimum (97 = "a") // Public UpperRangeLimit '4, Upper limit of range of response values, 255 is maximum (122 = "z") // Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Motor rotations are Circular (0 to 360) // Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs // Public Symbolic '1, Indicates that the values for this device are symbolic, Range a -> z // Public Magnitude '2, Indicates that the values for this device are numeric, integers, range 0 -> limit // Public Linear '1, Indicates that the values go from the lower limit to upper limit // Public Circular '2, Indicates that the values rap around from the upper limit to 0 // Public IntegerValues '1, Indicates that the values are integer readings // Public LogValues '2, Indicates that the values are already logs - orders of magnitude if (// Can't assign another new device number NumDevices == MaxDevices) { Stop("NumDevices == MaxDevices (" + NumDevices + ")"); } // There are only so many device types in DeviceValues array // currently set to 8 in Adaptron.Initialize_Adaptron() if (// don't have a device number yet so assign and return it DeviceNum == 0) { // The new device number for this device NumDevices = NumDevices + 1; // The returned device number DeviceNum = NumDevices; } else if (// else it is more than allowed DeviceNum > MaxDevices) { Stop("DeviceNum > MaxDevices (" + DeviceNum + "/" + MaxDevices + ")"); } else if (// else is it higher than the next one available DeviceNum > NumDevices + 1) { Stop("DeviceNum > NumDevices+1 (" + DeviceNum + "/" + (NumDevices + 1) + ")"); } else if (// else use the one passed in - overriding an existing device DeviceNum <= NumDevices) { } else if (// next device number provided DeviceNum == NumDevices + 1) { // The new device type number for this device = DeviceNum NumDevices = DeviceNum; } UseDevice = DeviceNum; if (// only 256 values allowed for response intensity IntensityRange > 256) { Stop("IntensityRange > 256 (" + IntensityRange + ")"); } Device[UseDevice] = DName; Devices[UseDevice][SymbolicOrMagnitude] = MagnOrSymb; // lower limit number / range of response values Devices[UseDevice][LowerRangeLimit] = LowerLimit; // upper limit number / range of response values Devices[UseDevice][UpperRangeLimit] = UpperLimit; // the symbolic responses DeviceResponses[UseDevice] = Responses; if (// Magnitude READINGS Devices[UseDevice][SymbolicOrMagnitude] == Magnitude) { // can be circular or linear Devices[UseDevice][LinearOrCircular] = LinOrCirc; // no symbolic responses are possible DeviceResponses[UseDevice] = ""; } else // Symbolic readings can not be circular { // non circular Devices[UseDevice][LinearOrCircular] = Linear; } Devices[UseDevice][IntegersOrLogs] = IntOrLog; // SetupBinonTypes(SenseOrDeviceNum, BinNam$, BinAbb$, IsASense, BinonTypReturned) SetupBinonTypes(UseDevice, BinonName, BinonAbbrev, IsDevice, BinTypNum); // The binon number usually = highest number so far Devices[UseDevice][PropertyBinonType] = BinTypNum.get(); // Fill in device info. on world page StringBuilder deviceInfo = new StringBuilder(); for (int Dvc = 1; Dvc <= NumDevices; Dvc++) { ping(); if (Devices[Dvc][SymbolicOrMagnitude] == Magnitude) { DisplayResponses = Devices[Dvc][LowerRangeLimit] + " to" + Devices[Dvc][UpperRangeLimit]; } else // symbolic values { DisplayResponses = DeviceResponses[Dvc]; DisplayResponses = mapCharacters(DisplayResponses, c -> eq(str(c), NoMoveOrTurn) ? ASpace : c); } deviceInfo.append(takeFirst(8, Device[Dvc] + ": ") + DisplayResponses + " " + SymbOrMagn(IsDevice, Dvc) + "\r\n"); } World.showDeviceValues(str(deviceInfo)); } // End of SetupDevice() public // Called from DesignBody.FinalSetup(), & ResetWld_Click() void Reset_Adaptron() { // Resets all changing info. to starting places. // Must be called before setting up any senses/sensors. int String; int D; int I; // necessary to reset the sequence ResetRnd(-1); OverLimit = false; // True if create all combinations, False if use only familiar parts CreateAll = false; // CreateAll = True ' // always starts with body pointing North BodyPointing = North; World.PointUnder(); // start with no senses NumSenses = 0; // start with no devices NumDevices = 0; // World.MoveDown() etc set this to indicate the direction the robot moved Motion = NoMove; // and it is used as the stimulus input of the Motion sense for (// +1 so it covers the Percept sense too I = 1; // +1 so it covers the Percept sense too I <= MaxSenses; // +1 so it covers the Percept sense too I++) { ping(); // Names of sense Sense[I] = ""; } // Initially the long term memory history is empty StoreAt = 0; // Initialize STMs // clear out memory display stuff - index into INPUTS$() and OUTPUTS$() LIN = 0; // Count of inputs COUNTIN = 0; // This clears BinonDisplay.ChngResults.Text and LTM ClearMemory(); for (I = 0; I <= 500; I++) { ping(); if (I > 0) { } for (String = 1; String <= MaxSenses; String++) { ping(); INPUTS[I][String] = ""; } for (D = 1; D <= MaxDevices; D++) { ping(); OUTPUTS[I][D] = ""; } } // Adapt.IO.Text = ""; // Adapt.LTMem.Text = ""; // UNUSED TriggerObj = NullObject; // set true if last response was reflexive. DoingReaction = false; DoingRepeat = false; // ActiveActon = NullAct; //no subconscious acton active // UNUSED ExploreObj = NullObject; //will be set if reflexive response done. // DoingAct1 = NullAct; //will be set if reflexive response done. // UNUSED NumTrigLinks = 0; //Number of LTM episodic action links // UNUSED NumActons = 0; // The number of Acts entries in use NumActs = 0; // Rotate through all reflexive acts RotateActs = false; // initialized so next one will be #2 - not the Relax response = #1 LastAct = 1; if (// Rotation through acts starts with Relax RotateActs) { LastAct = 0; } // persist changes change(); } // End of Reset-Adaptron() private void ResetRnd(int i) { // TODO } public void ClearMemory() { // Called by Reset_Adaptron() int Lk; int T; int I; for (I = 1; I <= MaxBinons; I++) { ping(); Binons[I][OLv] = 0; Binons[I][O1] = NullObject; Binons[I][O2] = NullObject; ZeroTheCounts(I); } // there are no binons NumBinons = 0; for (// For all property binons and their Percept combinations and Actions T = 1; // For all property binons and their Percept combinations and Actions T <= MaxBinonTypes; // For all property binons and their Percept combinations and Actions T++) { ping(); // The names and abbreviations for the various binon types BinonTypeName[T][BinName] = ""; BinonTypeName[T][BinAbbreviation] = ""; BinonTypes[T][SymbolicOrMagnitude] = Symbolic; // Pointer points back to sense or device BinonTypes[T][SensOrDevNum] = 0; } // clear SensorValues() and SensedBinons() ClearSenses(); // clear out all the perceptions in STM() ClearPerceptions(); TopLevel = 0; for (// Clear perceived Parallel Percept and property binon entries T = 1; // Clear perceived Parallel Percept and property binon entries T <= MaxPercepts; // Clear perceived Parallel Percept and property binon entries T++) { ping(); Percepts[T][BinId][Current] = NullObject; Percepts[T][BinId][Fired] = NullObject; Percepts[T][XQCnt][Current] = 0; Percepts[T][XQCnt][Fired] = 0; } for (// Clear out all targets Lk = 1; // Clear out all targets Lk <= MaxTargets; // Clear out all targets Lk++) { ping(); Targets[Lk][NLnk] = NullTarget; Targets[Lk][TargetBinon] = NullObject; } NumTargets = 0; ClearExpectations(); World.setBinonDisplayObjList(""); World.setBinonDisplayChngResults(""); // Percent JND = 20; // SizeBase# = 1.2 for a 20% just noticeable difference AssignBases(); // persist changes change(); } // End of ClearMemory() public // Called by ClearMemory() void ZeroTheCounts(// Called by ClearMemory() int Habit) { Binons[Habit][TQ] = 0; Binons[Habit][GQ] = 0; } // End ZeroTheCounts() public // Called by ClearMemory() void ClearSenses() { for (int Sens = 1; Sens <= MaxSenses; Sens++) { ping(); SensorValues[Sens][XQCnt][Fired] = 0; SensorValues[Sens][Valu][Fired] = 0; SensorValues[Sens][XQCnt][Current] = 0; SensorValues[Sens][Valu][Current] = 0; SensedBinons[Sens] = NullObject; } NumProperties = 0; } // End of ClearSenses() public // Used by ClearMemory() and processing STM perceptions in PerceptionAction() void ClearPerceptions() { // Clear out all the Current and previous perceptions that are sources for Habits in the STM() int Percpt; int Lvl; World.appendBinonDisplayChngResults(" ** Clearing Perceptions " + "\r\n"); for (Lvl = 1; Lvl <= MaxLevels; Lvl++) { ping(); for (Percpt = Fired; Percpt <= MaxLevels; Percpt++) { ping(); EmptySTM(Lvl, Percpt); } } } // End of ClearPerceptions() public // Called by ClearMemory() void AssignBases() { double Percnt; Percnt = /*Microsoft.VisualBasic.Conversion.Val*/ (JND) / 100.0; // 1.2 for a 20% just noticeable difference SizeBase = 1 + Percnt; // If it is 2.0 then that is a 100% just noticeable difference IntensityBase = 1 + Percnt; } // End of AssignBases() public final int Buckit(double Valuu, double Base) { // Base# = 1.2 'Ln(1.3) = 0.26, Ln(1.2) = 0.18 // XXX return (int) Math.round(100 * Math.log(Valuu) / Math.log(Base)); } // End of Buckit() public final void IdBinons(int OLvl, int Prt, int Obj1, int TQNum, int Obj2, int GQNum, int IDLRatio, int SeqOrPar, int ExpectIt, Var ObjId, Var NewOne) { // OLvl = Level of the binon, 1 stimulus property binons and response binons, 2+ Percepts or Action patterns // PrT = Property Type value // Obj1 = The left source binon // Obj2 = The right source binon // IDLRatio = The IDL ratio value // SeqOrPar = whether it is an Action sequence or a parallel Percept // ObjId = The object / binon identifier returned, = NullObject if over the limit // NewOne = Returned True if object newly created, False if it already existed. // If a new binon is created it is Active but Idle - waiting to repeat // ---- Binon Properties - 2nd index values // Public BType '1, The type of binon // Public O1 '2, Left source binon pointer // Public TQ '3, the count of times the trigger has fired // Public O2 '4, Right source binon pointer // Public GQ '5, the number of times the goal has fired // Public IDL '6, The ratio value of the binon // Public IntVl '7, Interest Value (NOVEL, INTERESTING, or Familiar) // Public OLv '8, Level of object = number of lowest level parts involved // Public SP '9, Sequential or Parallel property // Public TriggerList '10, points to the linked list of target binons [Targets()] // ' for which this binon is the left source binon (not the right source binon). // Public TriggerCount '11, Count of its sequential right targets, >1 means it has more than one goal // ' Used for prediction reliability, may be set >1 if needs to be combined with previous // Public GoalList '12, points to the linked list of target binons [Targets()] // ' for which this binon is the right source binon (not the left source binon) // Public GoalCount '13, Count of its sequential left targets, >1 means can not predict its trigger // ' Used for reliability of determining the cause, may be set >1 if needs to be combined with next // Public AE '14, Action (Percept - Act) or Attention (Act - Percept) level 1 Sequential binon // Given two objects/parts Obj1 and Obj2 // see if we have an object ObjId with the same values and the same Obj1 and Obj2. // Return the found or newly created binon if (Obj1 == 0) throw fail("obj1 = 0"); if (Obj2 == 0) throw fail("obj2 = 0"); if (// if can not find the exact match NumBinons >= MaxBinons) { ObjId.set(NullObject); World.appendBinonDisplayChngResults("\r\n" + "Binon limit of " + MaxBinons + " reached!"); Stop(); return; } // Return no binon - none created by default ObjId.set(NullObject); // Assume we will not find it already exists and will create a new one NewOne.set(true); // First determine if we have any binons of the given type with the given ratio if (// if none then do not check if ExistBinon NumBinons > 0) { // If the binons already exists then the ExistBinon routine sets the ObjId // ExistBinon(OLvl, PrTyp, Bin1&, Bin2&, V1, ItsAE, ObjId&) if (ExistBinon(OLvl, Prt, Obj1, Obj2, IDLRatio, ExpectIt, ObjId)) { // This applies to Percept and property binons only when attended to // DecreaseBinonInterest(BTyp, Bino&) DecreaseBinonInterest(ObjId.get()); NewOne.set(false); } } if (// If it does not already exist then create it ObjId.get() == NullObject) { // it was not found - so add it as a new one ObjId.set(NumBinons + 1); Binons[ObjId.get()][BType] = Prt; // The left source binon Binons[ObjId.get()][O1] = Obj1; Binons[ObjId.get()][TQ] = TQNum; // The right source binon Binons[ObjId.get()][O2] = Obj2; Binons[ObjId.get()][GQ] = GQNum; // stored object ratio values Binons[ObjId.get()][IDL] = IDLRatio; // Do level 1 binons become familiar immediately? No they should also go from Novel to Interesting to Familiar // Percepts start out Novel, then become Interesting and then Familiar // Perceptual sequences start out Novel and each time attention is paid to them they become Interesting and Familiar if (// If it is a Property or Percept binon then SeqOrPar == Parallel) { if (// if it is a Property binon then Prt <= NumProperties) { // Property binons start out Novel SetInterest(ObjId.get(), NOVEL); // Familiar for testing purposes SetInterest(ObjId.get(), FAMILIAR); } else // else it is a Percept binon { // Percept binons start out Novel SetInterest(ObjId.get(), NOVEL); // Familiar for testing purposes SetInterest(ObjId.get(), FAMILIAR); } } else { // Sequential binons start out Novel SetInterest(ObjId.get(), NOVEL); // tmp Call SetInterest(ObjId, FAMILIAR) 'Familiar - for testing } Binons[ObjId.get()][OLv] = OLvl; // Sequential or ParallelPrt, Binons[ObjId.get()][SP] = SeqOrPar; if (// AE value should be 0 SeqOrPar == Parallel && ExpectIt != 0) { Stop(); } // only used if SP=Sequential and OLvl=1, Action=1, Attention=2 Binons[ObjId.get()][AE] = ExpectIt; // =0, an NLnk pointer at end of linked list Binons[ObjId.get()][TriggerList] = NullTarget; // Count of its sequential right targets, >1 means can not predict its goal Binons[ObjId.get()][TriggerCount] = 0; // =0, an NLnk pointer at end of linked list Binons[ObjId.get()][GoalList] = NullTarget; // Count of its sequential left targets, >1 means can not predict its trigger Binons[ObjId.get()][GoalCount] = 0; // '--- Linked List of Target Binons - for Percepts and Actions ------------- // Public NumTargets& 'The number of Target binon entries created so far // Public MaxTargets& '10000 = the max number of Target binon entries possible // // Public Targets&(1 To 10000, 1 To 2) 'pointed to by Binons(Typ, ID, TriggerList) or by Binons(Typ, ID, GoalList) // '---- Targets' 2nd index property values // Public NLnk '1 = The pointer to the next Targets() entry in this linked list, // ' may be a NullTarget at end of linked list // Public TargetBinon '2 = a left or right Target binon // // Public NullTarget '=0, an NLnk pointer at end of linked list // The target binon ObjId is triggered by source binon Obj1 so add it to the right target list for Obj1 if (// cannot be property binon Obj1 != NullObject) { // create a new target NumTargets = NumTargets + 1; if (// have we exeeded the maximum NumTargets > MaxTargets) { Stop(); } // The right target is the newly created binon Targets[NumTargets][TargetBinon] = ObjId.get(); // It should point to the 1st one on existing list Targets[NumTargets][NLnk] = Binons[Obj1][TriggerList]; // ObjId becomes the 1st one on the right target list of Obj1 Binons[Obj1][TriggerList] = NumTargets; if (SeqOrPar == Sequential) { // Count of right targets for Obj1 Binons[Obj1][TriggerCount] = Binons[Obj1][TriggerCount] + 1; } } // The source binon Obj2 is the goal of this target binon ObjId so add it to the left target list of Obj2 if (// cannot be property binon Obj2 != NullObject) { // create a new target NumTargets = NumTargets + 1; if (// have we exeeded the maximum NumTargets > MaxTargets) { Stop(); } // The left target is the newly created binon Targets[NumTargets][TargetBinon] = ObjId.get(); // It should point to the 1st one on existing list Targets[NumTargets][NLnk] = Binons[Obj2][GoalList]; // ObjId becomes the 1st one on the left target list of Obj2 Binons[Obj2][GoalList] = NumTargets; if (SeqOrPar == Sequential) { // Count of left targets for Obj2 Binons[Obj2][GoalCount] = Binons[Obj2][GoalCount] + 1; } } NumBinons = ObjId.get(); // tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & " - Created New Binon = " & _ // DisplayStimulu[Prt][ObjId] + "\r\n"; } // End if not ExistBinon } // End of IdBinons() public final void DecreaseBinonInterest(int Bino) { // Updates the interest in a stimulus, Novel -> Interesting -> Familiar // called when the stimulus is added to the perception list // unused int Intrst; switch(InterestIn(Bino)) { case NOVEL: if (InterestLevels == 3) { // Novel -> Interesting SetInterest(Bino, INTERESTING); } else // Interestlevels=2 { // Novel -> Familiar SetInterest(Bino, FAMILIAR); } break; case INTERESTING: // Interesting -> Familiar SetInterest(Bino, FAMILIAR); break; } } // End of DecreaseBinonInterest() public final void SetInterest(int Objct, int IntLvl) { // Sets the interest level of the given object. Binons[Objct][IntVl] = IntLvl; } // End of SetInterest() public final int InterestIn(int Objct) { return Binons[Objct][IntVl]; } // End of Function InterestIn() public final boolean ExistBinon(int OLvl, int PrTyp, int Bin1, int Bin2, int V1, int ItsAE, Var ObjId) { boolean tempExistBinon = false; // Given two objects numbered Bin1 and Bin2 etc. see if we have an object in Binons() // that matches this combination, if so return its number in ObjId // ObjID = 0 if not found and ExistBinon is set to False // Ratios of Values are used for recognition of Time (duration) patterns // Pairs of object / binon parts (Obj1 and Obj2) are used for recognition of: // Sense patterns, sensor patterns and symbol patterns etc. int OO; // range of binons to search int StartAt; int EndAt; // assume it does not exist tempExistBinon = false; // return NullObject if not found ObjId.set(NullObject); StartAt = 1; EndAt = NumBinons; for (// For all the known objects of this type OO = StartAt; // For all the known objects of this type OO <= EndAt; // For all the known objects of this type OO++) { ping(); // Object level is an identifying property of a binon if (// If it is at the same level then Binons[OO][OLv] == OLvl) { if (// if it is the same binon type then Binons[OO][BType] == PrTyp) { // O1 = Object Part 1 pointer and O2 = Object Part 2 pointer // Given Id of the object - search for same pair of parts and AE if (Binons[OO][O1] == Bin1 && Binons[OO][O2] == Bin2 && Binons[OO][AE] == ItsAE) { if (// If it has the same quantity IDL Ratio? V1 == Binons[OO][IDL]) { ObjId.set(OO); tempExistBinon = true; // terminate FindIt loop OO = NumBinons; } } } } } return tempExistBinon; } // End of ExistBinon() public final void PerceptionAction(int[][][] SensorValues, Object[] DeviceValues) { // Called by Adapt.Inpu_KeyPress() for each stimulus/response cycle. // SensorValues() contains the stimuli from the senses/sensors // DeviceValues() are output responses to the devices to change the body/environment int ObjtLvl; int NovelLvl; String HabitIt = null; int Pass; boolean CheckIt = false; // Action-Expectation (Response-Stimulus) or Expectation-Action (Stimulus-Response) int AEorEA = 0; int SourceBinon; // unused int SourceXQCnt; // unused int SourceTQCnt; // 0. INITIAL STATE: based on the variables: PracticingBinon and ConcentrationLevel, will be either; // a) an Action being executed / practiced that identifies the expected Percept stimulus and // a concentration level of novel or interesting. Plus zero or more other Actions that also match // the attended-to past experience and have expectations of what will happen next. // // Or b) no Action being performed and concentration level of familiar but may have // a previous attended-to stimulus that repeated a certain quantity of times and is expecting it to repeat again. // // Or c) no attended-to stimulus or practicing Perceptual sequence because it is the first time through // In parallel there may be zero or more subconsciously executing Actions that will stop if they don't // get their next expected stimulus or their source binons become idle and will continue otherwise. StoreAt = StoreAt + 1; if (// stop further Go / Continue stepping StoreAt == MaxMemory) { // XXX World.Go.Enabled = false; } // display the cycle count World.setBinonDisplayChngResults("Step = " + StoreAt + "\r\n"); // 1. PERCEIVE PERCEPTS: // Get stimuli from all senses / sensors and recognize / create all Percept binon combinations of // familiar stimuli. Both source binons must be familiar before they can be combined. // This happens when a change occurs on any sense / sensor. This includes all areas of sensors that // attention is or is not focused on. This includes creation of stimuli that are expected and unexpected. // Novel stimuli get created and are remembered in the novel state. Is it possible that novel ones are only // kept if they have attention paid to them? When we sleep the novel ones are probably pruned. // Otherwise you end up with too many of them. Maybe it is only Actions that have to be attended to so // that their familiarity / interest is reduced. The interest of the Percept is reduced on occurrence repetition. // For a three stage novelty reduction, if and when Percepts occur again they are changed to Interesting. // The third time they occur they become familiar and can be combined with other familiar ones. // An Action has to be practiced before its interest level is reduced. // If there is a clock then // If RecogThem is called for every time it ticks (on a regular interval even if nothing changed) then // The sensor repeat count (Level1, XQCnt, Fired) should be set to 1. // (this is the case for hand writen digits or anywhere the environment is polled) // If the reading is Magnitude then level 1 needs to count the repeats of the same value within the JND // level 2 wil contain ratio binons (symbolic) // Else if RecogThem is called every time a change occurs on at least one sense then // Put the value of the duration into the sensors repeat count (XQCnt). (as for Morse code) // Else if there is no clock then // RecogThem is event driven and called only when a change occurs on at least one sense then // set the XQCnt to 1 and for any repeaters do as above for a clock. // SensorValues[NameBin][Valu][Fired] = Asc(Letr$) 'The letter // SensorValues[NameBin][XQCnt][Fired] = Durat 'the number of times it has repeated // SensorValues[ContBin][Valu][Fired] = DitDah 'The contrast intensity // SensorValues[ContBin][XQCnt][Fired] = Durat 'the number of times it has repeated // Pay attention to the expected sensors if concentrating - a Percept, // create the Percepts that attract attention and place the most interesting in STM(1,Fired) // Set GotAttendedTo = true if got the expected/attendedto stimuli/Percept // Process the SensorValues() ProcessStimuli(SensorValues); // The Perception STM list has many binons at each level. The Fired one is the most recent fired binon // before any processing has been done at that level. It is put in the Fired entry when // the level below is processed. // After the processing has been done the previous one contains what was in the Current and // the Current contains what was in the Fired provided there was no repeat of an Action. // 2. PERFORM ACTION RECOGNITION: // High level algorithm - 30th December 2016 // Expectation = Expectation/Attention binon = A-R // Action = Action Habit = R-A // Perceptual sequence = Stimulus Habit (Percept at level 1) and = A-E at higher levels = R-A-R // Action sequence = Response Habit (Device responses) and E-A higher up = A-R-A. // Repeat the the algorithm below for these two situations: // Pass 1/ Odd level Current Action sequence combined with Fired Perceptual sequence to produce next level up Fired Expectation, // find out if right target Action of the Perceptual sequence is worth doing and then // the even level Current Action is combined with just Fired Expectation to produce next level up Perceptual sequence, // Find out if right target Action sequence of the Expectation is worth doing. // Pass 2/ Odd level Current Perceptual sequence combined with Fired Action sequence to produce next level up Fired Action, // find out if right target Expectation of the Action sequence is worth doing and then // the even level Current Expectation is combined with just Fired Action to produce next level up Action sequence, // find out if right target Perceptual sequence of the Action is worth doing. // The algorithm: Repeat this for each level X of the STM() binon tree as long as the fired is not a null object // If on an even level and doing pass 2/ then have a just Fired Action to process so // check to see if the fired Action pattern matches the previous Action (X positions earlier) at this level // If it repeats then increment the past entry for the repeat and move it up to current // Else if it does not repeat or on an odd level or doing pass 1/ then // combine the Current to the Fired at this level (if there is a current) and // place it in the next level up Fired position // end if // If finished pass 1/ STM processing then use the highest level Action or Action sequence found worth doing and // do its lowest level response. Put this response Action sequence in STM(level 1 Fired) and start pass 2 // If finished pass 2/ STM processing then use the highest level Expectation or Perceptual sequence found worth doing and // attend to its lowest level expected Percept in ProcessStimuli(). // The stimulus Percept obtained will be the Fired Perceptual sequence to start this process again. for (// For 1/ R-S & A-E combinations then 2/ S-R & E-A combinations Pass = 1; // For 1/ R-S & A-E combinations then 2/ S-R & E-A combinations Pass <= 2; // For 1/ R-S & A-E combinations then 2/ S-R & E-A combinations Pass++) { ping(); // Start by processing level 1 perceptions - always assigned ObjtLvl = 1; // set to the level at which the fired STM is novel NovelLvl = 0; // Move right amount to eliminate previous pattern MoveAmount = 0; // It may be a right source binon for some target binons SourceBinon = STM[ObjtLvl][BinId][Fired]; while (// While there is a Fired familiar binon in STM SourceBinon != NullObject) { ping(); World.appendBinonDisplayChngResults(StringHelper.trim(String.valueOf(ObjtLvl), ' ') + "-0/ Processing percepts at level" + vbToStr(ObjtLvl) + "\r\n"); // First move the STM entries right by the MoveAmount due to a repeater at a lower level if (MoveAmount > 0) { // declare undeclared variable int Prcpt = 0; // eliminates binon created with previous goal from STM MoveRight(ObjtLvl, Current + MoveAmount, Current, 2 * Prcpt); } if (// If the STM fired binon is novel then InterestIn(SourceBinon) > FAMILIAR) { // It can not be combined with a current NovelLvl = ObjtLvl; } else // else check for a repeat and combine with current in STM { // do not check for a repeat of an Action CheckIt = false; if (// If the Stimulus / Expectation processing pass Pass == 1) { AEorEA = Attention; HabitIt = "Percept"; if (// Odd level = 1, Even level = 0 ObjtLvl % 2 == 0) { HabitIt = "Action"; // Check to see if it repeats - both A and E - even levels CheckIt = true; } } else if (// else if the Action / Response processing pass Pass == 2) { // assume it will be an Action AEorEA = Action; HabitIt = "Action"; if (// If fired entry is an Action then (Pass=2 and remainder =0) ObjtLvl % 2 == 0) { HabitIt = "Expectation"; // Check to see if it repeats - both A and E - even levels CheckIt = true; } } World.appendBinonDisplayChngResults(StringHelper.trim(String.valueOf(ObjtLvl), ' ') + "-0a/ Pass" + vbToStr(Pass) + " - " + HabitIt + " Processing" + "\r\n"); ProcessSTMLevel(ObjtLvl, SourceBinon, AEorEA, CheckIt); } // End if STM Fired binon is Novel // Move all STM left, the fired entry into the current location MoveLeft(ObjtLvl); // Remember the highest not null fired level in STM HighestPerceptLvl = ObjtLvl; if (// track highest non-empty level HighestPerceptLvl > TopLevel) { TopLevel = HighestPerceptLvl; } // Go up the pattern tree combining Fired and Currents if they are patterns and fired is not nullobject // check out the next level for current and fired ObjtLvl = ObjtLvl + 1; if (ObjtLvl <= MaxLevels) { // It may be a right source binon for some target binons or Null SourceBinon = STM[ObjtLvl][BinId][Fired]; } else { SourceBinon = NullObject; Stop(); } } // Move all higher levels left by one minus moveamount // move left one but right based on repeater found MoveAmount = 1 - MoveAmount; for (; // for all higher levels that have something in them ObjtLvl <= TopLevel; // for all higher levels that have something in them ObjtLvl++) { ping(); if (MoveAmount == 1) { // processed one more level 1 stimulus MoveLeft(ObjtLvl); } else if (MoveAmount < 0) { MoveRight(ObjtLvl, Current - MoveAmount, Current, 2 * ObjtLvl); } } // Fill in the top part of BinonDisplay.ChngResults.Text ReportObjects1(); // It may be a right source binon for some target binons SourceBinon = STM[HighestPerceptLvl][BinId][Current]; if (Pass == 1) { // If finished pass 1/ STM processing then based on the recognized Perceptual sequence or Expectation find any // predicted action and use this highest level Action or Action sequence found worth doing and // do its lowest level response in PerformAction(). // Or if the predicted action is learnt / familiar then use thinking (deduction) and find one worth doing // Put this response Action sequence in STM(level 1, Fired) and start pass 2 // determine what response to produce - do thinking DetermineResponse(); // Keep a record of STM() binons for display of LTM LTMEMORY[StoreAt][LtmESType] = BinonTypeOf(SourceBinon); LTMEMORY[StoreAt][LtmESActBin] = SourceBinon; World.appendBinonDisplayChngResults(DisplaySTM()); } else // else Pass = 2 { // If finished pass 2/ STM processing then based on the recognized Action or Action sequence find any // predicted perception and use this highest level Expectation or Perceptual sequence found worth doing and // do its lowest level expected Percept and attend to it in ProcessStimuli(). // This effectively means DetermineStimulus() needs to determine what stimulus to attend to // The stimulus Percept obtained will be the Fired Perceptual sequence to start this process again. // Keep a record of STM() binons for display of LTM LTMEMORY[StoreAt][LtmARType] = BinonTypeOf(SourceBinon); LTMEMORY[StoreAt][LtmARActBin] = SourceBinon; // The level 1 perceived stimulus could be a familiar stimulus but unexpected. // It is unexpected because none of the active Perceptual sequences were expecting it. // Reports on Percepts() and STM() & expectation ReportPerceptions(); // Report on Binons ReportObjects2(); } // End if Pass =1 or Pass = 2 } } // End of PerceptionAction() public final // Called from PerceptionAction() void ProcessStimuli(// Called from PerceptionAction() int[][][] SensorValues) { // SensorValues() contains the sensor readings for ProcessStimuli() to process. // ProcessStimuli() is not currently provided with the Percept that it expects to get/should attend to. // Instead ProcessStimuli() assumes that the previous stimuli will repeat and just delivers any changes. // ProcessStimuli is asked to attend to the senses / sensors specified in the given Percept (not yet). // After calling ProcessSenses() to put sensory stimuli from all senses into SensedBinons() it // uses the SenseBinons() and puts the perceived ones in the Percepts(). Not yet based on what was being attended to. // If nothing was attended to then all the sensory stimuli are used. // It creates the parallel combinations (Percepts) of the property SensedBinons(). // Combinations are formed if the parts are both familiar and both changed or both familiar and not changed. // The most interesting Percept is then the largest / highest level (most complex) one that changed or // if there was no change then just the highest level one. // The most interesting stimulus is then placed in STM(level 1, Fired). // SenseBinons() consist of: // TextBin = the symbolic value for the letter - symbolic // ContBin = Intensity = the value for the sensor measurement - Magnitude int Sens; int PerceptType; String GotWhat; int TopType; int TopBinon; int TopInterest; int OL; boolean HaveAChange = false; int RepeatCount; int FirstBinon; int IntInF = 0; int SecondBinon; int TheType; // Property binons and their combinations are at level 1 OL = 1; // Assume no change will take place on any sense HaveAChange = false; // The expectation is the previous stimulus will repeat // Report on all Percepts, Actions and expectations ReportPerceptions(); // Obtain the SensedBinons() for all property types SensorValues() ProcessSenses(OL, SensorValues); // The expectation is a repeat of the previous stimuli (if there are any) Property and Percept binons. // Magnitude stimuli values must change by a JND to be detected // Symbolic stimuli values are always available because they are uniquely identified. // Determine what attracts attention by combining the stimuli that have changed. // If nothing has changed then a repeat of the previous stimuli has occurred. // For all the senses/property and Percept types // copy the SensedBinons() into the 1st level Fired Percepts (property binons level), // the other Percept combinations of property binons are created below for (// For each property type = sense Sens = 1; // For each property type = sense Sens <= NumSenses; // For each property type = sense Sens++) { ping(); TheType = Sens; Percepts[TheType][XQCnt][Fired] = SensorValues[Sens][XQCnt][Fired]; // Property binons into Percepts Level 1 Percepts[TheType][BinId][Fired] = SensedBinons[Sens]; if (// use the previous SensedBinon Percepts[TheType][BinId][Current] != NullObject) { if (SensedBinons[Sens] != Percepts[TheType][BinId][Current]) { // This property binon has changed HaveAChange = true; } } else // Else the Current entry is empty the first time through { if (StoreAt != 1) { Stop(); } } } // end for each property binon // Create all the combinations of Percepts CreatePerceptCombos(); // Report on Percept perceptions DisplayPercepts(Fired); // ------ What attracts attention and thus what to pay attention to / focus on // The highest level, most interesting changed, not null current Percept binon // captures attention for sequential processing // Will be the highest complexity if no changed one found TopBinon = NullObject; TopType = NullType; if (HaveAChange) { // The interest level of the highest changed binon TopInterest = NoInterest; for (// For all the Percept binon types from complex to property binons PerceptType = NumPercepts; // For all the Percept binon types from complex to property binons PerceptType >= 1; // For all the Percept binon types from complex to property binons PerceptType--) { ping(); // The Percept that fired of this type - maybe NullObject FirstBinon = Percepts[PerceptType][BinId][Fired]; // The previous or expected binon of this type - maybe NullObject SecondBinon = Percepts[PerceptType][BinId][Current]; if (// If the fired one is different / changed then FirstBinon != SecondBinon) { // If have a perceived binon and an expected one then if (FirstBinon != NullObject) { // Interest level of this Percept IntInF = InterestIn(FirstBinon); // If it is familiar and interest so far is also familiar then we use the largest changed combination if (IntInF == FAMILIAR) { if (// The first / highest familiar one TopInterest == NoInterest) { // subroutine UseThisOne TopType = PerceptType; // Save the highest level changed interesting Percept TopBinon = FirstBinon; // will be familiar - only used if HaveAChange=True TopInterest = IntInF; } // Else if it is novel then use the lowest level highest interest that has changed } else if (// If it is more or equal interest than the one so far then IntInF >= TopInterest) { // subroutine UseThisOne TopType = PerceptType; // Save the highest level changed interesting Percept TopBinon = FirstBinon; // will be familiar - only used if HaveAChange=True TopInterest = IntInF; } } else // else one or both binons are NullObjects { } // End if it has a value } else // else got expected - no difference / change { } // End if it has changed } // If there is no change then the largest (highest level) not null combination is focused on. } else // else there is no change in stimuli { for (// For all the Percept binon types from complex to property binons PerceptType = NumPercepts; // For all the Percept binon types from complex to property binons PerceptType >= 1; // For all the Percept binon types from complex to property binons PerceptType--) { ping(); // The Percept that fired of this type - maybe NullObject FirstBinon = Percepts[PerceptType][BinId][Fired]; if (FirstBinon != NullObject) { // subroutine UseThisOne TopType = PerceptType; // Save the highest level changed interesting Percept TopBinon = FirstBinon; // will be familiar - only used if HaveAChange=True TopInterest = IntInF; // terminate loop PerceptType = 1; } } } if (// report about a different stimulus then - unexpected HaveAChange) { GotWhat = "Got UNEXPECTED: "; } else // else we got what was expected { GotWhat = "Got EXPECTED: "; } World.appendBinonDisplayChngResults(rep(' ', 55) + GotWhat + DisplayPattern(TopBinon) + "\r\n"); // Clears PracticingBinon, PerceivedBinon etc. ClearExpectations(); // Must have a property or Percept stimulus so place the value Percepts(..Fired) // in the Fired entry of STM[) at level 1][set its XQ count][set ExpectLevel, Expcts(] etc. RepeatCount = 0; if (TopBinon != NullObject) { RepeatCount = Percepts[TopType][XQCnt][Fired]; // FireTheBinon(PercptLvl, TheBinon&, TQCnt, XQCnt) // will set the XQ count and the Perceived etc. FireTheBinon(OL, TopBinon, 1, RepeatCount); RememberStimulus(TopBinon, StoreAt); } // Move the fired Percepts() actually sensed into the current entries and clear the Fired entries for (// For all property and Percept binon types PerceptType = 1; // For all property and Percept binon types PerceptType <= NumPercepts; // For all property and Percept binon types PerceptType++) { ping(); Percepts[PerceptType][BinId][Current] = Percepts[PerceptType][BinId][Fired]; // clear their entries Percepts[PerceptType][BinId][Fired] = NullObject; Percepts[PerceptType][XQCnt][Current] = Percepts[PerceptType][XQCnt][Fired]; Percepts[PerceptType][XQCnt][Fired] = 0; } } // End of ProcessStimuli() public final // Called from ProcessStimuli() void ProcessSenses(// Called from ProcessStimuli() int OL, // Called from ProcessStimuli() int[][][] SensorValues) { // Goes through the Raw sensor data in SensorValues(), creates the property type SensedBinons(). // SensorValues consist of: // Text = the symbolic value for the letter - symbolic // Intensity = the value for the sensor measurement - Magnitude var SensedBinon = new Var<>(0); var NewBee = new Var<>(false); int PropBinonType; int PrevLogVal; int FiredLogVal; int ValuDiff; // ' -------------------------- Senses and Sensors -------------------------- // // Public NumSenses 'The number of physical senses, Max of 8 // 'Currently equals the NumProperties since each sense currently = 1 property type // Public MaxSenses 'Maximum number of senses = max 8 physical senses // unused String[] Sense = new String[1 + 8]; //Names of senses, up to 8 physical senses // // Public Senses[1 To 8][1 To 6] 'Properties of the different senses // '1st index = Sense number // '2nd index = Sense property // // '---- Senses() - 2nd index values - Sense Properties // Public PropertyBinonType '1, Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin // Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator // Public LowerRangeLimit '3, Lower limit of range of values, zero is minimum (65 = "A") // Public UpperRangeLimit '4, Upper limit of range of values, 255 is maximum (90 ="Z") // Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360) // Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs // Public NumberOfSensors '7 Number of sensors in sensor array // Public SensorsDependentOrIndependent '8 are sensors adjacent (dependent) or independent // // Public Symbolic '1, Indicates that the values from this sense are symbolic, range A -> Z // Public Magnitude '2, Indicates that the values from this sense are numeric, integers, range 0 -> Limit // // Public Linear '1, Indicates that the values go from the lower limit to upper limit // Public Circular '2, Indicates that the values rap around from the upper limit to 0 // // Public IntegerValues '1, Indicates that the values are integer readings // Public LogValues '2, Indicates that the values are already logs - orders of magnitude // '-------------------- Values of stimuli from senses / sensors ------------------------------ // // Public SensorValues[1 To 8][1 To 2][0 To 1] 'Stimulus values from senses/sensors // '1st index is sense number, currently = property binon type // '2nd index is what type of information is in the SensorValues(), XQCnt or Valu // '3rd index is Fired for the most recent stimulus value and Current for the previous // // '---- SensorValues 2nd index values - type of information in SensorValues() // Public XQCnt '=1, the count of times the value has repeated, also used below // Public Valu '=2, the value for the stimulus, if symbolic then value = Asc(Symbol$) // Public NoName$ '"_", The character used when no letter provided for the IDL value of a TextBin binon // // '---- SensorValues 3rd index values - which past stimulus it is - also used below // Public Fired '=0 'stimulus put in this level upon firing before being processed // Public Current '=1 'The Fired one becomes the Current one after processing // ------ Create binons from Sensed values that have changed and put them in SensedBinons() // and move the fired SensorValues to the previous entries for all senses = property types for (// For each sense (TextBin and ContBin) = for each property type int Sens = 1; // For each sense (TextBin and ContBin) = for each property type Sens <= NumSenses; // For each sense (TextBin and ContBin) = for each property type Sens++) { ping(); // In Morse code only one property per sense PropBinonType = Sens; if (// If symbolic then Senses[Sens][SymbolicOrMagnitude] == Symbolic) { // Symbolic values always put in SensedBinons() whether they changed or not. // Create or find the binon for this symbolic value // IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean) IdBinons(OL, PropBinonType, NullObject, 0, NullObject, 0, SensorValues[Sens][Valu][Fired], Parallel, 0, SensedBinon, NewBee); // Fired Symbolic value changed SensedBinons[Sens] = SensedBinon.get(); } else // Else ValueType = Magnitude { // Goal FiredLogVal = Buckit(SensorValues[Sens][Valu][Fired], SizeBase); // The first time though we will not have a previous (Current) sensor reading (PrevLogVal) if (// no previous value SensorValues[Sens][Valu][Current] == 0) { // there is a change in the Magnitude reading ValuDiff = 1; } else { // Trigger PrevLogVal = Buckit(SensorValues[Sens][Valu][Current], SizeBase); // Adjacent repeat quantities are used to produce a ratio - same as these two lines of code: // ValuDiff = Int(Abs(PrevLogVal - FiredLogVal) / 100) 'the difference in the Logs = ratio of repeats // If FiredLogVal > PrevLogVal Then ValuDiff = -ValuDiff 'keep the sign // Trigger minus Goal Logs ValuDiff = (PrevLogVal - FiredLogVal) / 100; } // Using ValuDiff will produce values of 1 and -1 as the contrast (Intensity) SensorValues() // IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, _ // IDLRatio, SeqOrPar, ExpectIt, ObjId, NewOne As boolean); IdBinons(OL, PropBinonType, NullObject, 0, NullObject, 0, ValuDiff, Parallel, 0, SensedBinon, NewBee); // Fired Magnitude value changed by a JND SensedBinons[Sens] = SensedBinon.get(); } // save the previous value SensorValues[Sens][Valu][Current] = SensorValues[Sens][Valu][Fired]; // save the previous repeat count SensorValues[Sens][XQCnt][Current] = SensorValues[Sens][XQCnt][Fired]; } // End of loop for each property type = sense } // End of ProcessSenses() public final // Create all the combinations of Percepts void CreatePerceptCombos() { var SensedBinon = new Var<>(0); var NewBee = new Var<>(false); int PropBinonType; int OL; int FirstType; int FirstBinon; int IntInF; boolean FirstChanged = false; int SecondType; int SecondBinon; int IntInS; boolean SecondChanged = false; // For all the possible pairs of not null 1st level Percepts() = Property binon level // Create the 2nd and higher level combinations, // combine changed with changed and no change with no change but only if both property binons are familiar. // Fill in Percepts() with a NullObject if either source binon is a NullObject or novel // Need to create the Percept combinations of property binons - data driven algorithm from PerceptSources() for (// PropBinonType used for position of the combination PropBinonType = NumProperties + 1; // PropBinonType used for position of the combination PropBinonType <= NumPercepts; // PropBinonType used for position of the combination PropBinonType++) { ping(); FirstType = PerceptSources[PropBinonType][FirstSource]; SecondType = PerceptSources[PropBinonType][SecondSource]; OL = PerceptSources[PropBinonType][PerceptLevel]; // CombineThem; //Uses Percepts[TheType][BinId][Current] to determine change // CombineThem: FirstBinon = Percepts[FirstType][BinId][Fired]; SecondBinon = Percepts[SecondType][BinId][Fired]; // assume the combination will not be produced Percepts[PropBinonType][BinId][Fired] = NullObject; if (// if both sources are not null FirstBinon != NullObject && SecondBinon != NullObject) { IntInF = InterestIn(FirstBinon); IntInS = InterestIn(SecondBinon); // Both source binons must be familiar before they can be combined if (CreateAll || (IntInF == FAMILIAR && IntInS == FAMILIAR)) { // Both source binons must have changed or both stayed the same before they can be combined // Percepts[TheType][BinId][Current] FirstChanged = false; if (Percepts[FirstType][BinId][Current] != FirstBinon) { FirstChanged = true; } SecondChanged = false; if (Percepts[SecondType][BinId][Current] != SecondBinon) { SecondChanged = true; } if (// If both changed or both stayed the same then FirstChanged == SecondChanged) { // IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean) IdBinons(OL, PropBinonType, FirstBinon, 0, SecondBinon, 0, 0, Parallel, 0, SensedBinon, NewBee); // exp Call SetInterest(PropBinonType, SensedBinon, FAMILIAR) 'Percept binons always familiar // The property combination binon has fired (been recognized) and is expecting to fire again Percepts[PropBinonType][BinId][Fired] = SensedBinon.get(); // Need value in Fired because it will be moved into current Percepts[PropBinonType][XQCnt][Fired] = Percepts[FirstType][XQCnt][Fired]; } else // else no combination binon created at level 1 - Source Percepts() are not familiar & changed { } } else // else no combination binon created at level 1 - Source Percepts() are not familiar { } } else // else no combination binon created at level 1 - Source Percepts() are NullObjects { } // end of CombineThem } } // End CreatePerceptCombos() public final // called from PerceptionAction() void ActivateAction(// called from PerceptionAction() int DoBinon) { // DoBinon& is the PracticingBinon Action that is to be done var DHabitBinon = new Var<>(0); // GetDHabit returns the Action or D-Habit Binon // Get the level 1 D-Habit to perform GetDHabit(DoBinon, DHabitBinon); PerformDHabit(DHabitBinon.get()); } // End of ActivateAction() public final // called from ActivateAction() void PerformDHabit(// called from ActivateAction() int DoBinon) { // DoBinon is a level 1 Binon (D-Habit) that contains the device response to perform. // DoBinon after pass 1 has been done is the expected response. // It calls PerformResponses() which performs the DoBinon. // This means it outputs the LetrBin. Then it fires the binon so it is on the STM(). var Letter = new Var<>(""); // unused int LetterBinon = 0; int DeviceNum = 0; // unused boolean NewBee = false; int OutType; int OutBinon = 0; // '-------------------- Devices ------------------------------------------------ // // Public NumDevices 'Number of output devices // Public MaxDevices 'Maximum number of devices = max 8 devices // Public Device$(1 To 8) 'Names of device, up to 8 devices // // Public Devices[1 To 8][1 To 5] 'Properties of the output / response devices // '1st index = Device number // '2nd index = Device property // Public DeviceResponses$(1 To 4) 'A string of the possible symbolic responses for the device // ---- Devices() - 2nd index values - Device Properties - DEFINED ABOVE // Public PropertyBinonType '1, Response property binon type e.g. 1 = LetrBin // Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator // Public LowerRangeLimit '3, Lower limit of range of response values, zero is minimum (97 = "a") // Public UpperRangeLimit '4, Upper limit of range of response values, 255 is maximum (122 = "z") // Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Motor rotations are Circular (0 to 360) // Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs // Public Symbolic '1, Indicates that the values for this device are symbolic, Range a -> z // Public Magnitude '2, Indicates that the values for this device are numeric, integers, range 0 -> limit // Public Linear '1, Indicates that the values go from the lower limit to upper limit // Public Circular '2, Indicates that the values rap around from the upper limit to 0 // Public IntegerValues '1, Indicates that the values are integer readings // Public LogValues '2, Indicates that the values are already logs - orders of magnitude // Find the response parts of DoBinon - should use Devices() to identify the binon types involved if (// If there was no response in DoBinon then DoBinon == NullObject) { // should always have one selected by DetermineResponse() Stop(); // DeviceNum = 1 'Letters = LetrBin // OutType = Devices[DeviceNum][PropertyBinonType] 'Currently = LetrBin for device #1 // Letter$ = NoResp$ // 'Should distinguish between symbolic versus Magnitude responses // 'Create or find the binon for this symbolic value // 'IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean) // Call IdBinons(1, OutType, NullObject, 0, NullObject, 0, Asc(Letter$), Parallel, 0, OutBinon, NewBee) } else // else have a letter to output { OutBinon = DoBinon; OutType = BinonTypeOf(DoBinon); // the device number for this response type binon DeviceNum = BinonTypes[OutType][SensOrDevNum]; } // Output the response (if any) and setup the expectation // GetValue adds text to 3rd parameter = Letter$ so empty it Letter.set(""); GetValue(OutBinon, Letter); Letter.set(StringHelper.trim(Letter.get(), ' ')); World.appendBinonDisplayChngResults(" OUTPUT response = " + Letter + "\r\n"); DeviceValues[DeviceNum][XQCnt] = 1; DeviceValues[DeviceNum][Valu] = Binons[OutBinon][IDL]; // Clears PerceivedBinon ClearExpectations(); // FireTheBinon(PercptLvl, TheBinon&, TQCnt, XQCnt) // will set PerceivedBinon FireTheBinon(1, OutBinon, 1, 1); RememberResponse(OutBinon, StoreAt); } // End PerformDHabit() public final void ReportPerceptions() { // Display the Fired, Current and previous perceptions in Percepts() // unused String OLvl = null; // unused String Prcpt = null; // unused String Pcpts = null; DisplayPercepts(Current); // Report on Perceptual sequence perceptions World.appendBinonDisplayChngResults(DisplaySTM() + "\r\n"); } // End of ReportPerceptions() public final void DisplayPercepts(int CurrOrFired) { int BinType; // Report on Percept recognitions World.appendBinonDisplayChngResults(" Percepts = "); for (// All binon types except Actions BinType = 1; // All binon types except Actions BinType <= NumPercepts; // All binon types except Actions BinType++) { ping(); World.appendBinonDisplayChngResults(DisplayPercept(BinType, CurrOrFired)); } World.appendBinonDisplayChngResults("\r\n"); } // End of DisplayPercepts() public final String DisplayPercept(int BType, int CurrOrFired) { return StringHelper.trim(String.valueOf(Percepts[BType][XQCnt][CurrOrFired]), ' ') + "x" + DisplayPattern(Percepts[BType][BinId][CurrOrFired]) + " "; } // End of DisplayPercept$() public final String DisplaySTM() { String tempDisplaySTM = ""; int OLvl; int Prcpt; String Pcpts; // Report on perceptions in STM() if (// No STM entries then STM[1][BinId][Current] == NullObject) { tempDisplaySTM = "STM is empty" + "\r\n"; } else { for (OLvl = 1; OLvl <= MaxLevels; OLvl++) { ping(); // printVars_str DisplaySTM(+OLvl, +MaxLevels); // empty this line Pcpts = ""; for (// find out if any are not null at this level Prcpt = OLvl + 2; // find out if any are not null at this level Prcpt >= Fired; // find out if any are not null at this level Prcpt--) { ping(); if (STM[OLvl][BinId][Prcpt] != NullObject) { Pcpts = Pcpts + DisplaySTMEntry(OLvl, Prcpt) + " "; } } if (// Only if there was a fired entry !Pcpts.equals("")) { // Put level # at start of line Pcpts = " " + "Lvl=" + StringHelper.trim(String.valueOf(OLvl), ' ') + " " + Pcpts; tempDisplaySTM = tempDisplaySTM + Pcpts + "\r\n"; } else // else no current entry at this level { // terminate the loop OLvl = MaxLevels; } } tempDisplaySTM = tempDisplaySTM + "\r\n"; } return tempDisplaySTM; } // End of DisplaySTM$() public final String DisplaySTMEntry(int Percpt, int CurrFired) { int BinonId; // unused String BinonSt = null; var VL = new Var<>(""); BinonId = STM[Percpt][BinId][CurrFired]; GetValue(BinonId, VL); // display 6 chars of pattern VL.set(substring(substring(VL.get(), 0, 20) + " ", 0, 7)); return "#" + StringHelper.trim(vbToStr(CurrFired), ' ') + "=" + StringHelper.trim(String.valueOf(STM[Percpt][XQCnt][CurrFired]), ' ') + "x" + StringHelper.trim(String.valueOf(STM[Percpt][TQCnt][CurrFired]), ' ') + DisplayStimulu(BinonId) + " " + VL; } // End of DisplaySTMEntry$() public final String DisplayPattern(int StimBin) { String tempDisplayPattern; var BinonTyp = new Var<>(""); var VL = new Var<>(""); int NumChr; int StimTyp; StimTyp = BinonTypeOf(StimBin); if (StimTyp == NullType) { tempDisplayPattern = " ~ "; } else if (// Have a type but no binon StimBin == NullObject) { GetTypeInfo(StimTyp, BinonTyp, VL); tempDisplayPattern = VL.get().substring(0, 2) + " ~"; } else { // Level 2 is 11 characters, level 3 is 17 characters NumChr = 5 + 6 * (StimTyp - 1); GetValue(StimBin, VL); tempDisplayPattern = DisplayStimulu(StimBin) + " " + substring(VL.get(), 0, NumChr); } return tempDisplayPattern; } // End of DisplayPattern$() public final String DisplayStimulu(int StimBin) { String tempDisplayStimulu; var BTyp = new Var<>(""); var Rdg = new Var<>(""); String Inf; String Gl; int StimTyp; StimTyp = BinonTypeOf(StimBin); if (StimBin == NullObject || StimTyp == NullType) { tempDisplayStimulu = "-00"; } else { GetTypeInfo(StimTyp, BTyp, Rdg); Gl = StringHelper.trim(Rdg.get().substring(0, 2), ' ') + StringHelper.trim(String.valueOf(StimBin), ' '); Inf = IntSymb(InterestIn(StimBin)); tempDisplayStimulu = Inf + Gl + AESR(StimBin); } return tempDisplayStimulu; } // End of DisplayStimulu$() public final String InterestSymbol(int BinNum) { int IntIn; IntIn = InterestIn(BinNum); return IntSymb(IntIn); } // End of InterestSymbol$() public String IntSymb(Object Intrst) { String tempIntSymb; tempIntSymb = ASpace; switch((Integer) Intrst) { case NOVEL: tempIntSymb = chr(254); break; case INTERESTING: tempIntSymb = "!"; break; case FAMILIAR: tempIntSymb = "-"; break; } return tempIntSymb; } // End of IntSymb$() public // Called by ClearMemory(), ProcessStimuli() and PerformAction() void ClearExpectations() { PerceivedBinon = NullObject; } // End of ClearExpectations() public final void FireTheBinon(int PercptLvl, int TheBinon, int TQCount, int XQCount) { // Called from ProcessStimuli() for the most changed stimulus combination // Called from CreateCombo which is called by ProcessSTMLevel() every time a familiar stimulus is experienced // Called from PerformAction() after response produced // The binon has fired so place it in the Fired entry at this level in the STM, increment its XQ count, // idle it and make it the most recent target of its left and right source binons. // A newly created binon can not fire - can not be put on the STM() int Uselink; // Make it the most recent target binon of its left and right source binons ImYourMostRecent(TheBinon, TriggerList); ImYourMostRecent(TheBinon, GoalList); if (InterestIn(TheBinon) != NOVEL) { if (// If a valid binon has fired TheBinon != NullObject) { STM[PercptLvl][BinId][Fired] = TheBinon; if (// should be zero STM[PercptLvl][XQCnt][Fired] != 0) { Stop(); } // It has fired this many times STM[PercptLvl][XQCnt][Fired] = XQCount; // trigger firing count for comparison of size of repeaters STM[PercptLvl][TQCnt][Fired] = TQCount; // BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & " + Binon " & _ // DisplayPattern$(TheType, TheBinon) & " Fired" & vbCrLf // // Want the PerceivedBinon to be the highest fired Perceptual or Action sequence binon // that triggers at least one associating binon or the level-1 S or R that has no associating binon if (// If at level-1 start with the S or R PercptLvl == 1) { // Track the trigger of expected goal for the Action PerceivedBinon = TheBinon; } else { if (// If on an odd level - Perceptual - or Action sequence then isSorR(TheBinon)) { // determine its first associating binon, if any Uselink = FloatingPointToInteger.ToInt32(MostRecentTriggerTargetLink(TheBinon)); if (// If the fired binon has at least one associating binon Uselink != NullTarget) { // Track the trigger of expected goal for the Action PerceivedBinon = TheBinon; } else // else use the previously assigned PerceivedBinon { } } else // else we are on an even level - A- or Expectation { // Stop } } } else { // The fired binon should never be null Stop(); } } else // else it is novel and can not be put on STM() { String Res = (" " + PercptLvl).substring((" " + PercptLvl).length() - 5) + vbToStr(Binons[TheBinon][TriggerCount]) + vbToStr(Binons[TheBinon][GoalCount]) + " " + DisplayPattern(TheBinon) + " NEW" + "\r\n"; World.appendBinonDisplayChngResults("\r\n" + Res); } // End If TheBinon is not novel } // End of FireTheBinon() public final void ImYourMostRecent(int HabBinon, int TriggerOrGoal) { int SourceBinon; int TgtLink; int TgtBinon; int PrevLink; int FirstLink; boolean FoundIt = false; if (TriggerOrGoal == TriggerList) { // Left source binon - trigger SourceBinon = Binons[HabBinon][O1]; } else { // Right source binon - goal SourceBinon = Binons[HabBinon][O2]; } if (SourceBinon != NullObject) { // Find the target binon on the trigger or goal list of the source binon and move it to the front of the list TgtLink = Binons[SourceBinon][TriggerOrGoal]; FirstLink = TgtLink; FoundIt = false; PrevLink = NullTarget; while (!FoundIt) { ping(); if (// should have been on the list TgtLink == NullTarget) { Stop(); } // The target binon TgtBinon = Targets[TgtLink][TargetBinon]; if (// If it matches the HabBinon then found the entry TgtBinon == HabBinon) { FoundIt = true; if (// If not at the start of the list already PrevLink != NullTarget) { // remove the TgtLink Targets() entry from linked list Targets[PrevLink][NLnk] = Targets[TgtLink][NLnk]; // TgtLink Targets() entry points to old first one on list Targets[TgtLink][NLnk] = FirstLink; // It is now the 1st one / most recent target of source binon Binons[SourceBinon][TriggerOrGoal] = TgtLink; } } else { // Link for the previous Targets() entry PrevLink = TgtLink; // go to the next link in Targets list TgtLink = Targets[TgtLink][NLnk]; } } } } // End of ImYourMostRecent() public final double MostRecentTriggerTargetLink(int TheBinon) { double tempMostRecentTriggerTargetLink; // Called from FireTheBinon() when upadting STM() and DetermineResponse() when thinking int TgtLink; // Obtain the link to the most recent (first) target ActBin for the trigger // The list of all targets for which it is the trigger TgtLink = Binons[TheBinon][TriggerList]; tempMostRecentTriggerTargetLink = NullTarget; if (// If TheBinon has any sequential right targets then Binons[TheBinon][TriggerCount] > 0) { while (TgtLink != NullTarget) { ping(); if (// The type of right target binon of the the given stimulus BinonTypeOf(Targets[TgtLink][TargetBinon]) == ActBin) { tempMostRecentTriggerTargetLink = TgtLink; // found the first useful Perceptual sequence - terminate the loop TgtLink = NullTarget; } else // else some of the right targets could be Percepts? { // skip Percepts TgtLink = Targets[TgtLink][NLnk]; } } } return tempMostRecentTriggerTargetLink; } // End of MostRecentTriggerTargetLink() public final void GetDHabit(int TheBinon, Var FoundBinon) { // This finds the level-1 D-Habit or response binon for the given binon (TheBinon - may be an Action) and // returns it as the expected binon (FoundBinon - may be a D-Habit or response binon) // unused int NameBinon = 0; // If it is the NullObject then that is returned FoundBinon.set(TheBinon); while (BinonTypeOf(FoundBinon.get()) == ActBin) { ping(); FoundBinon.set(Binons[FoundBinon.get()][O2]); } // Now the Found binon type is a D-Habit binon } // End of GetDHabit() public final // called by PerceptionAction() void ProcessSTMLevel(// called by PerceptionAction() int ObjtLvl, // called by PerceptionAction() int SourceBinon, // called by PerceptionAction() int AorE, // called by PerceptionAction() boolean CheckRepeat) { // If CheckRepeat then determine if the Fired at this level is same as repeat position. // If it is a repeater then increases its count. // Then combines the Current and Fired entries and puts them at one level higher in STM // The fired binon at ObjtLvl is still in Fired position in STM when done. int Prcpt; int TQFired; int XQFired; int OldPercBin; int TQRepeat; int TrgtLvl; // tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & Trim(Str$(ObjtLvl)) & "-0a/ Fired binon " & _ // DisplayPattern[SourceType][SourceBinon] + "\r\n"; // check to see if the pattern matches the previous pattern at this level // if it matches then // increment the past entry for the repeat and move it up to current // Repeater at this level will be in this entry position Prcpt = ObjtLvl; TrgtLvl = ObjtLvl + 1; if (// If need to check if an Action or Expectation repeats then CheckRepeat) { World.appendBinonDisplayChngResults(StringHelper.trim(String.valueOf(ObjtLvl), ' ') + "-0c/ Check for repeater Action" + "\r\n"); // Any repeater should be in the correct position = ObjtLvl OldPercBin = STM[ObjtLvl][BinId][Prcpt]; if (// If the old = Fired it is a repeat binon OldPercBin == SourceBinon) { // Trigger quantity (size) of the SourceBinon just fired TQFired = STM[ObjtLvl][TQCnt][Fired]; // Trigger quantity (size) for the older Prcpt binon TQRepeat = STM[ObjtLvl][TQCnt][Prcpt]; if (// If the repeater is the same size as the fired one then TQRepeat == TQFired) { // tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & Trim(Str$(ObjtLvl)) & "-0b/ Pattern " & _ // DisplayPattern[SourceType][SourceBinon] + " Repeats" + "\r\n"; // Increment its repeat count by the number of time it fired (duration at level 1) XQFired = STM[ObjtLvl][XQCnt][Fired]; STM[ObjtLvl][XQCnt][Prcpt] = STM[ObjtLvl][XQCnt][Prcpt] + XQFired; MoveAmount = MoveAmount + ObjtLvl; // MoveRight(ObLvl, FromEntry, ToEntry, UpTo) // repeater ends up in Fired entry MoveRight(ObjtLvl, Prcpt, Fired, 2 * Prcpt); // clear the fired next level up EmptySTM(TrgtLvl, Fired); } else // same pattern but different size { // Stop 'OK - treat as not repeating // tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & Trim(Str$(ObjtLvl)) & "-0c/ Pattern " & _ // DisplayPattern(SourceType, SourceBinon) + " does Not repeat" + "\r\n"; } } else { // tmp BinonDisplay.ChngResults.Text = BinonDisplay.ChngResults.Text & Trim(Str$(ObjtLvl)) & "-0c/ Pattern " & _ // DisplayPattern(SourceType, SourceBinon) + " does Not repeat" + "\r\n"; } } // If it does not repeat // Then as a goal combine the trigger previous to it at this level // (if there is a trigger) and place it in the next level up fired position if (// If there is a trigger previous to the fired location STM[ObjtLvl][BinId][Current] != NullObject) { if (// and there is a goal at the repeater position STM[ObjtLvl][BinId][Fired] != NullObject) { if (// set to 0 if already used ObjtLvl > 1 || STM[ObjtLvl][XQCnt][Current] != 0) { // Place the result in Fired of level above CreateCombo(ObjtLvl, Current, AorE); } else { // why? Stop(); } if (Prcpt + 2 <= MaxLevels) { // Remove used trigger binon EmptySTM(ObjtLvl, Prcpt + 2); } } else // The fired binon is NullObject { Stop(); } } } // End ProcessSTMLevel() public final void MoveRight(int ObLvl, int FromEntry, int ToEntry, int UpTo) { // Move all the entries at the ObLvl to the right so that the one at FromEntry ends up at ToEntry position // Null out previous locations, stop when the From Entry reaches the UpTo position int Prcpt; int NewPrcpt; int Distance; // how far they have to move Distance = FromEntry - ToEntry; if (UpTo > MaxLevels) { UpTo = MaxLevels; } for (Prcpt = FromEntry; Prcpt <= UpTo; Prcpt++) { ping(); NewPrcpt = Prcpt - Distance; MoveOnePerception(ObLvl, Prcpt, NewPrcpt); // Nullify where it came from EmptySTM(ObLvl, Prcpt); } } // End MoveRight() public final void MoveLeft(int ObLvl) { // Move all the entries at this ObLvl to the left one position so the Fired is in the Current int Prcpt; boolean HaveAPercept = false; int ToPrcpt; // assume this level is empty HaveAPercept = false; ToPrcpt = ObLvl + 2; if (ToPrcpt >= MaxLevels) { ToPrcpt = MaxLevels - 1; } for (Prcpt = ToPrcpt; Prcpt >= Fired; Prcpt--) { ping(); if (STM[ObLvl][BinId][Prcpt] != NullObject) { HaveAPercept = true; } // Move it left one position MoveOnePerception(ObLvl, Prcpt, Prcpt + 1); } // and clear the fired entry EmptySTM(ObLvl, Fired); if (!HaveAPercept) { TopLevel = TopLevel - 1; } } // End MoveLeft() public final void MoveOnePerception(int ObLvl, int FromEntry, int ToEntry) { STM[ObLvl][BinId][ToEntry] = STM[ObLvl][BinId][FromEntry]; STM[ObLvl][XQCnt][ToEntry] = STM[ObLvl][XQCnt][FromEntry]; STM[ObLvl][TQCnt][ToEntry] = STM[ObLvl][TQCnt][FromEntry]; } // End of MoveOnePerception() public void EmptySTM(int OLvl, int PrevCurrFired) { STM[OLvl][BinId][PrevCurrFired] = NullObject; STM[OLvl][XQCnt][PrevCurrFired] = 0; STM[OLvl][TQCnt][PrevCurrFired] = 0; } // End of EmptySTM() public final void CreateCombo(int ObjtLvl, int TrigPrcpt, int AorE) { // If it is possible, Combine the trigger (Current) and goal (Fired) binons in the STM() int TriggerBinon; int TQNum; int IntInTrig; int Bin12; int TQCount; int GoalBinon; int GQNum; int IntInGoal; int Bin21; int Prev1LogRpts; int Prev2LogRpts; int RptsDiff; var ResultBinon = new Var<>(0); int TgtLvl; var NewBee = new Var<>(false); int Bin11; int Bin22; boolean CombineThem = false; // Returned NullObject if not found or created ResultBinon.set(NullObject); TriggerBinon = STM[ObjtLvl][BinId][TrigPrcpt]; if (ObjtLvl == 1) { // wait until it has stopped repeating STM[ObjtLvl][TQCnt][TrigPrcpt] = STM[ObjtLvl][XQCnt][TrigPrcpt]; } if (// If have a trigger pattern then TriggerBinon != NullObject) { GoalBinon = STM[ObjtLvl][BinId][TrigPrcpt - 1]; if (// and if have a goal pattern then GoalBinon != NullObject) { IntInTrig = InterestIn(TriggerBinon); IntInGoal = InterestIn(GoalBinon); if (// if both familiar then IntInTrig == FAMILIAR && IntInGoal == FAMILIAR) { Bin12 = Binons[TriggerBinon][O2]; Bin21 = Binons[GoalBinon][O1]; // If at source level 2 or higher they must overlap // or they are adjacent at source level = 1 if ((ObjtLvl > 1 && Bin12 == Bin21) || ObjtLvl == 1) { // When the 1st binon left source is specific enough to uniquely predict its next stimulus // and the 2nd binon right source is specific enough to uniquely predict its previous stimulus and // when the common source binon (Bin12 = Bin21) uniquely predicts both its goal and // trigger binon then stop combining the trigger (TriggerBinon) with the goal (GoalBinon). CombineThem = true; if (ObjtLvl > 1) { CombineThem = false; Bin11 = Binons[TriggerBinon][O1]; Bin22 = Binons[GoalBinon][O2]; if (// ****** NOTE add True to the condition to turn off Binons[Bin11][TriggerCount] != 1 || Binons[Bin22][GoalCount] != 1 || Binons[Bin21][TriggerCount] != 1 || Binons[Bin21][GoalCount] != 1) { CombineThem = true; } } if (CombineThem) { // the repeat value of the trigger - XQ count TQNum = STM[ObjtLvl][XQCnt][TrigPrcpt]; // the repeat value of the goal - XQ count GQNum = STM[ObjtLvl][XQCnt][TrigPrcpt - 1]; // Use the trigger and goal binons to create a new binon with // the correct ratio and place it in the Fired perception at the TgtLvl TgtLvl = ObjtLvl + 1; // Trigger Prev1LogRpts = Buckit(TQNum, SizeBase); // Goal Prev2LogRpts = Buckit(GQNum, SizeBase); // Adjacent repeat quantities are used to produce a ratio - same as: // QtyDiff = Int(Abs(Prev1LogRpts - Prev2LogRpts) / 100) // the difference in the Logs = ratio of repeats // If Prev2LogRpts > Prev1LogRpts Then RptsDiff = -RptsDiff 'keep the sign // Trigger minus Goal Logs RptsDiff = (Prev1LogRpts - Prev2LogRpts) / 100; // The new binon is Active but Idle - waiting for a repeat // IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean) IdBinons(TgtLvl, ActBin, TriggerBinon, TQNum, GoalBinon, GQNum, RptsDiff, Sequential, AorE, ResultBinon, NewBee); // The binon has fired so place it in the Fired entry at the target level, increment its XQ count, // idle it and make it the most recent target of its trigger and goal. // The size of the lowest level left part TQCount = STM[ObjtLvl][TQCnt][TrigPrcpt]; // Add the fired stimulus to the Perceived STM(). // FireTheBinon will set the XQ count and the PerceivedBinon. // FireTheBinon(PercptLvl, TheBinon&, TQCnt, XQCnt) // will set the XQ count FireTheBinon(TgtLvl, ResultBinon.get(), TQCount, 1); } } // End if they overlap properly } // End if they are both familiar } else // Else the fired one is Nullobject { // It should not be possible for fired one to be NullObject ' Stop(); } // End if the goal binon exists } else // Else the trigger is NullObject { // It should be not NullObject - already checked in ProcessSTMLevel() Stop(); } // End if the trigger binon exists } // End of CreateCombo() public final void ReportObjects1() { // Report information after perception and attention - before practice // Reports only the objects perceived in BinonDisplay.ChngResults String Res; String Ptrn; int ExprObj; // -------------------------- Status of perception before attending to the stimuli -------------- if (Processing50) { return; } World.appendBinonDisplayChngResults("\r\n" + " # EObj Pattern - Fired Binon List" + "\r\n"); Res = ""; for (var J = 1; J <= HighestPerceptLvl; J++) { ping(); ExprObj = STM[J][BinId][Current]; if (ExprObj != NullObject) { Ptrn = ""; if (// If we have an expected binon at this level then ExprObj == PerceivedBinon) { Ptrn += " This is the Perceived or Performed Binon"; } Res = Res + (" " + J).substring((" " + J).length() - 5) + vbToStr(Binons[ExprObj][TriggerCount]) + vbToStr(Binons[ExprObj][GoalCount]) + " " + DisplayPattern(ExprObj) + " " + Ptrn + "\r\n"; } } World.appendBinonDisplayChngResults(Res + "\r\n"); } // End ReportObjects1() public final void ReportObjects2() { // Report after Pass 2 - after prerceiving stimulus, doing response and expecting a stimulus // Reports on Objects in ObjList textbox StringBuilder Res2 = new StringBuilder(); var Rdgs = new Var<>(""); StringBuilder Res1; String Ptrn; String IntInfo; var VL = new Var<>(""); var Ty1 = new Var<>(""); var Ty2 = new Var<>(""); // unused String BN = null; // unused String Brand = null; int BnTyp; int Objct; var BinTyp = new Var<>(""); int ObjLvl; // unused int Prcpt; int TypInteger; String Inf = null; // -------------------- The binon list after being processed ------------ if (Processing50) { return; } // Fill in Binon list in BinonDisplay.ObjList.Text int NumChr; for (// Property binons and Percept combinations, Perceptual sequences and Responses BnTyp = 1; // Property binons and Percept combinations, Perceptual sequences and Responses BnTyp <= NumBinonTypes; // Property binons and Percept combinations, Perceptual sequences and Responses BnTyp++) { ping(); // Rdgs$ = abbreviation - not used - use BinTyp$ only GetTypeInfo(BnTyp, BinTyp, Rdgs); Res2.append(BnTyp).append(", ").append(Rdgs).append(BinTyp).append("\r\n"); for (// For each level of binons ObjLvl = 1; // For each level of binons ObjLvl <= MaxLevels; // For each level of binons ObjLvl++) { ping(); Res1 = new StringBuilder(); for (// For all binons Objct = 1; // For all binons Objct <= NumBinons; // For all binons Objct++) { ping(); Ptrn = ""; if (// if have a binon at this level then Binons[Objct][OLv] == ObjLvl) { if (BinonTypeOf(Objct) == BnTyp) { Inf = ""; VL.set(""); GetValue(Objct, VL); // Level 2 is 11 characters, level 3 is 17 characters NumChr = 5 + 6 * (Binons[Objct][OLv] - 1); // display 14 chars of pattern Ptrn = substring(VL.get(), 0, NumChr); if ((Ptrn == null ? 0 : Ptrn.length()) == 1) { Ptrn = " " + Ptrn; } TypInteger = BinonTypeOf(Binons[Objct][O1]); GetTypeInfo(TypInteger, Ty1, Ty1); TypInteger = BinonTypeOf(Binons[Objct][O2]); GetTypeInfo(TypInteger, Ty2, Ty2); IntInfo = InterestSymbol(Objct); Res1.append(substring(" " + Objct, (" " + Objct).length() - 3)).append(substring((" " + Binons[Objct][OLv]), (" " + Binons[Objct][OLv]).length() - 3)).append(AESR(Objct)).append(" ").append(substring(Ty1.get(), 0, 2)).append(substring(" " + Binons[Objct][O1], (" " + Binons[Objct][O1]).length() - 3)).append(" ").append(substring(Ty2.get(), 0, 2)).append(substring(" " + Binons[Objct][O2], (" " + Binons[Objct][O2]).length() - 3)).append(substring(" " + Binons[Objct][IDL], (" " + Binons[Objct][IDL]).length() - 4)).append(takeLast(2, vbToStr(Binons[Objct][TriggerCount]))).append(takeLast(2, vbToStr(Binons[Objct][GoalCount]))).append(substring(" " + IntInfo, (" " + IntInfo).length() - 3)).append(substring(" " + Binons[Objct][TQ], (" " + Binons[Objct][TQ]).length() - 3)).append(substring(" " + Binons[Objct][GQ], (" " + Binons[Objct][GQ]).length() - 3)).append(" ").append(Ptrn).append(" ").append(DisplayHabit(Objct)).append("\r\n"); } } // End if it is this Binon type } if (!StringHelper.isNullOrEmpty(Res1.toString())) { Res2.append(Res1).append("\r\n"); } } Res2.append("\r\n"); } // value set above World.setBinonDisplayObjList(Res2.toString()); } // End of ReportObjects2() public final String AESR(int Objct) { String tempAESR; if (// AE property is 0 for parallel binons BinonTypeOf(Objct) <= NumPercepts) { // Level 1 Percept or property binon tempAESR = " P"; } else { // level 1 Response binon = LetrBin tempAESR = " A"; } if (// AE not assigned for level 1 Stimuli or Responses Binons[Objct][AE] == Action) { if (// two letters refer to types/roles of source binons !isSorR(Objct)) { // Action binon tempAESR = " A"; } else { // Action sequence tempAESR = " AA"; } } else if (Binons[Objct][AE] == Attention) { if (!isSorR(Objct)) { // Expectation binon tempAESR = " E"; } else { // Perceptual sequence tempAESR = " PP"; } } return tempAESR; } // End of AESR$() public final boolean isSorR(int Objct) { // If the binon is at an odd sequential level then it is either an S or R // If the binon is at an even sequential level then it is either an A or an E // If the binon is not sequential (an ActBin) then it is either an S or R // remainder is 1 if odd level, 0 if even level return Binons[Objct][OLv] % 2 == 1 || BinonTypeOf(Objct) != ActBin; } public final String DisplayHabit(int ObjBin) { StringBuilder tempDisplayHabit; // Displays the list of target binons for which this one is the left source and / or right source int Link; // unused int Bin = 0; tempDisplayHabit = new StringBuilder(); // Display the list of target binons this one triggers // does the binon trigger at least one target binon Link = Binons[ObjBin][TriggerList]; while (Link != NullTarget) { ping(); // add target binon type and objID tempDisplayHabit.append("l").append(DisplayStimulu(Targets[Link][TargetBinon])); // go to the next one on the list Link = Targets[Link][NLnk]; if (Link != NullTarget) { tempDisplayHabit.append(", "); } } // does the binon goal at least one target binon Link = Binons[ObjBin][GoalList]; if (Link != NullObject && !StringHelper.isNullOrEmpty(tempDisplayHabit.toString())) { tempDisplayHabit.append(", "); } while (Link != NullTarget) { ping(); // add target binon type and objID tempDisplayHabit.append("r").append(DisplayStimulu(Targets[Link][TargetBinon])); // go to the next one on the list Link = Targets[Link][NLnk]; if (Link != NullTarget) { tempDisplayHabit.append(", "); } } return tempDisplayHabit.toString(); } // End of DisplayHabit() public final // Called from PerceptionAction() void DetermineResponse() { // Enter here if finished pass 1/ STM processing then based on the recognized Perceptual sequence or Expectation find any // predicted action and use this highest level Action or Action sequence found worth doing and // do its lowest level response in PerformAction(). // Or if the predicted action is learnt / familiar then use thinking (deduction) and find one worth doing // Put this response Action sequence in STM(level 1, Fired) and start pass 2 int FirstLink; int Thinklink; int ThinkBinon; // unused int EndLink = 0; String Reason = null; // unused int GoalBinon = 0; // unused int TrigTargetBinon = 0; // The binon being practiced. Concentration Level is based upon it. var PracticingBinon = new Var<>(0); int DoneBinon; var NewBee = new Var<>(false); int OutType; int UL; int ll; int NextResponse; var ResponseBinon = new Var<>(0); int I; int CurrentResponse; int UseResponse; int HaveResponse; int NumberOfResponses; String ThisResponse = null; // FireTheBinon() will have found any response worth doing and PerceivedBinon will be the level // for the Perceptual sequence trigger to find the response to do. // The Practicing binon may be the NullObject because no Actions were being performed. // This happens when there are no Actions for the stimulus as the trigger. // This means no expectation. After a stimulus is familiar and the one following it is also familiar then // we have a novel Action for the trigger and at least have one expectation // Note: it should be just the perceived binon that is used based on any number >0 triggercount // the interest in redoing its most recent determines if need to practice it. triggercount=1 needed to // do deductions - certain / reliable inference, if >1 then just the most recent possible goal is used // and this gives induction reasoning - no certainty because sometime in the past at least one different goal has happened // even after thinking then babble PracticingBinon.set(NullObject); // If have a perceived binon (it is an Perceptual sequence) with associating Action binons then // check to see if it is worth doing - if not then think // The right target binon link - if any FirstLink = FloatingPointToInteger.ToInt32(MostRecentTriggerTargetLink(PerceivedBinon)); if (// If have a link to a recent right target Action binon then FirstLink != NullTarget) { // This must be an Action PracticingBinon.set(Targets[FirstLink][TargetBinon]); if (// If it is worth doing then InterestIn(PracticingBinon.get()) > FAMILIAR) { Reason = " STM Perceived binon is the trigger of its most recent novel Action"; // use PracticingBinon below by calling ActivateAction() } else // else the binon is not worth practicing so think about it { // #1 Approach: ---------------------------- // An alternate approach here is to go up the most recent right target binons of the tree // looking for an Action that is novel and if found then activate all the right targets traversed so // that the sequence is done at a concentration level to repeat / learn the novel one. // Let us just try one traversal up this right target binon tree via the intermediate Perceptual sequence. // The right target binon link - if any Thinklink = FloatingPointToInteger.ToInt32(MostRecentTriggerTargetLink(PracticingBinon.get())); // This will be an Perceptual sequence - but we need to go up one more level to the Action - if any if (// If there is a right target link to an associating binon then Thinklink != NullTarget) { ThinkBinon = Targets[Thinklink][TargetBinon]; // The right target Action binon link - if any Thinklink = FloatingPointToInteger.ToInt32(MostRecentTriggerTargetLink(ThinkBinon)); } else // Else no right target Perceptual sequence binon { } // #2 Approach: ---------------------------- // Obtain the response that could be performed and see if it triggers an Expectation (stimulus) worth expecting // 2 GoalBinon = Binons[PracticingBinon][O2] 'The goal that could be done - Action sequence // 2 Thinklink = MostRecentTriggerTargetLink(GoalBinon) 'Does it have a right target - an Expectation // 2 Reason$ = " Thought about associated goal of STM perceived is trigger of a most recent novel Expectation" // ----------------------------------------- if (// If there is a right target link to an associating binon then Thinklink != NullTarget) { // The Approach#1 Action or Approach#2 Expectation to practice ThinkBinon = Targets[Thinklink][TargetBinon]; if (// if the next A- or Expectation is worth expecting then InterestIn(ThinkBinon) > FAMILIAR) { // there is a next Perceptual sequence to expect so do the current Action - PracticingBinon // use PracticingBinon below by calling ActivateAction() Reason = " Thought about right target of STM perceived is trigger of a most recent novel Action"; } else // Else the next Action sequence (goal of PracticingBinon) is not worth doing so { // do not do the practicing binon - it is familiar / learnt PracticingBinon.set(NullObject); } // End if the next binon was worth doing } else // else there is no next possible stimulus - no associating Expectation so { // do not do the practicing binon - it is familiar / learnt PracticingBinon.set(NullObject); } // End if there was no next Perceptual sequence to expect } // End if the associating Action (PracticingBinon) is worth doing } else // Else no right target link of PerceivedBinon - no PracticingBinon { } // End of Is there a right target link of Perceived binon // If don't have a binon to practice, even after thinking, then find something to do or babble if (// If the PracticingBinon is still a NullObject then PracticingBinon.get() == NullObject) { Reason = ""; // If the Practicing Binon is null because the highest STM recognized Perceptual sequence (PerceivedBinon) // has no associating Action binons (is novel or familiar but followed by a novel binon) then // we do nothing to see if it repeats int DeviceNum; if (// If there is no associating binons for the perception FirstLink == NullTarget) { // so use the 1st device and its first symbolic or range response, PracticingBinon must be set // Letters = LetrBin DeviceNum = 1; // Currently = Wheels for device #1 OutType = Devices[DeviceNum][PropertyBinonType]; if (// Use Range of values Devices[DeviceNum][SymbolicOrMagnitude] == Magnitude) { NextResponse = Devices[DeviceNum][LowerRangeLimit]; // IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean) IdBinons(1, OutType, NullObject, 0, NullObject, 0, NextResponse, Parallel, 0, PracticingBinon, NewBee); } else // If Devices[DeviceNum][SymbolicOrMagnitude] = Symbolic Then 'Use first response values { // Will be a NoResp$ String Letter = DeviceResponses[DeviceNum].substring(0, 1); // Letter$ = NoResp$ // Create or find the binon for this symbolic value // IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean) IdBinons(1, OutType, NullObject, 0, NullObject, 0, asc(Letter), Parallel, 0, PracticingBinon, NewBee); } Reason = " First response of first action device - Babbling"; } else // else have an associating Action sequence for PerceivedBinon then { // Find the most recent response at the lowest level and use the next one // The Action most recently practiced at the next level up DoneBinon = Targets[FirstLink][TargetBinon]; // GetDHabit returns the lowest level response binon in ResponseBinon // Get the level 1 most recent response done GetDHabit(DoneBinon, ResponseBinon); // the device number for this response type binon DeviceNum = BinonTypes[BinonTypeOf(ResponseBinon.get())][SensOrDevNum]; if (// Use Range of values Devices[DeviceNum][SymbolicOrMagnitude] == Magnitude) { ll = Devices[DeviceNum][LowerRangeLimit]; UL = Devices[DeviceNum][UpperRangeLimit]; if (// If it is the no response then Binons[ResponseBinon.get()][IDL] == NoResp) { NextResponse = ll; } else { NextResponse = Binons[ResponseBinon.get()][IDL] + 1; if (// if off end of valid values then NextResponse > UL) { // wrap around to start again NextResponse = ll; } } // Create or find the binon for this symbolic value // IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean) IdBinons(1, BinonTypeOf(ResponseBinon.get()), NullObject, 0, NullObject, 0, NextResponse, Parallel, 0, PracticingBinon, NewBee); } else // If Devices[DeviceNum][SymbolicOrMagnitude] = Symbolic Then 'Use given response values { // Find the last one used CurrentResponse = 0; NumberOfResponses = DeviceResponses[DeviceNum].length(); for (// go through the response string I = 1; // go through the response string I <= NumberOfResponses; // go through the response string I++) { ping(); if (Binons[ResponseBinon.get()][IDL] == asc(DeviceResponses[DeviceNum].substring(I - 1, I - 1 + 1))) { CurrentResponse = I; // terminate the loop I = NumberOfResponses; } } // Find the next non "z" entry UseResponse = CurrentResponse; // will be set to the next response entry position HaveResponse = 0; // 'A random response generator // While HaveResponse = 0 // UseResponse = Int(NumberOfResponses * Rnd + 1) 'generate a number between 1 and and NumberofResponses // ThisResponse$ = Mid$(DeviceResponses$(DeviceNum), UseResponse, 1) // 'if it is a response that can be done and not a repeat of the last one chosen then // If ThisResponse$ <> NoMoveOrTurn$ And UseResponse <> CurrentResponse Then // HaveResponse = UseResponse 'a non-zero value will terminate the loop // End If // Wend // Sequentially go through the available responses while (HaveResponse == 0) { ping(); UseResponse = UseResponse + 1; if (// if off the end of the string then UseResponse > NumberOfResponses) { // start at the beginning again UseResponse = 1; } ThisResponse = DeviceResponses[DeviceNum].substring(UseResponse - 1, UseResponse - 1 + 1); if (// if it is a response that can be done then !ThisResponse.equals(NoMoveOrTurn)) { // a non-zero value will terminate the loop HaveResponse = UseResponse; } } // Create or find the binon for this symbolic value // IdBinons(OLvl, Prt, Obj1&, TQNum, Obj2&, GQNum, IDLRatio, SeqOrPar, ExpectIt, ObjId&, NewOne As Boolean) IdBinons(1, BinonTypeOf(ResponseBinon.get()), NullObject, 0, NullObject, 0, asc(ThisResponse), Parallel, 0, PracticingBinon, NewBee); } Reason = " Babbling"; } // End if have no associating Action sequence } else // Else have a binon to practice so do that one { } // End if do not have a PracticingBinon // Report on what is being practiced - if anything if (// If practicing then PracticingBinon.get() != NullObject) { World.appendBinonDisplayChngResults(" * Practicing " + DisplayPattern(PracticingBinon.get()) + Reason + "\r\n"); } else { Stop(); World.appendBinonDisplayChngResults(" * Not Practicing anything" + "\r\n"); } // If have no action to practice at this point then PerformAction() will respond with nothing // Perform the response and fire the binon to STM(1, Fired) ActivateAction(PracticingBinon.get()); // Old notes // If we are practicing (concentrating on) an Action then this active sequence will have a goal // that it is trying to achieve. This is the goal of the most recent target binon (Action) triggered by the // previously perceived/attended-to stimulus. It is the prediction, the expectation. // The concentration level will be based on the wanted / pleasant (desirability) level of the goal or // interest level (novel, interesting or familiar) of the redo interest of the Action being practiced. // When practicing / concentrating we will only attend to the expected goal of the Action being practiced. // All of the triggered target binons of the attended to stimulus are active / expecting but only the most recent one // is being practiced, goal expected. // If any expecting Action (including the one being practiced) does not get its expected goal then it becomes inactive. // The binon recognized (fired) instead will be on the Percepts() list and attract attention. // Thus the possible outcomes are: // O1 - Get the expected goal of the practicing Action binon (PracticingResult$ = "Matched" // O2 - Get the goal of a different triggered Expecting target Action binon (same triggering / attended-to binon) // O3 - All expecting Actions could fail // O3a - get a familiar goal stimulus but it is a novel sequence for the attended-to as the trigger // O3b - get a novel or interesting stimulus at the AttendToLevel or lower. // Note: you can be attending to a stimulus but not practicing because there are no right target Action binons // of the attended-to stimulus. // Note: only target Sequence / Action binons can be performed / practiced - not target property binons // If concentrating - no expecting binon got its goal so - Outcome O3 // we find the "got-instead" goal // This "got-instead" goal binon is the one obtained instead of the expected goal // or if that is not available (a NullObject) then it is the next attended-to stimulus (the novel one produced). // The logic should be: // 1 If practicing an Action then (PracticingResult$ will be set Matched or Failed) // When practicing an Action you are paying attention / focusing on / expecting a stimulus from sense of its goal // 2 If it matched its goal and the goal has finished repeating then focus / pay attention to its goal. [set as AttendTo] // Reduce its interest / novelty level. // Can not be distracted because paying attention to the goal sense (change blindness) and got the goal? // Or will any stimulus not expected by any of the other Actions (not being practiced) distract you? [set AttendTo] // else it failed to match / get the goal of the practicing binon so // the one being practiced stays at the same interest level. // The actual sequence experienced becomes the most recent one (but no change in its interest level). // Attention is paid to the stimulus "got-instead" of the goal at the same sense as the goal unless // there is a stimulus that distracts you from this. [set AttendTo] // Else not practicing so // Pay attention to the most interesting - attractive? stimulus [set AttendTo] // End // // ' The interest in a sequence is only reduced if it is the one being practiced and the goal is matched. // ' What about another sequence that has the same trigger and its goal is expected but it is not the one being // ' practiced but it is the one that is matched? It stays novel. If it becomes the most recent it will be practiced // ' the next time its trigger occurs. // 'If not practicing (e.g. due to a novel or interesting attended-to stimulus) then // ' Attend to the most attractive perception // ' If the attendto is novel or interesting, it can not be the left source for any target binons // ' and has no goals. // ' If the attendto is a novel Percept then we must remain not practicing (ConcentrationLevel = NoInterest). // ' If the attendto is an Action then pay attention to the goal stimulus that caused the novel // ' sequence. It will be familiar. Start practicing any // ' If the attendto is familiar then // ' use it as the trigger and its most recent sequential right target as an Action worth practicing. // ' Set the concentration level based on the wanted (pleasant) goal (must be familiar) or // ' the interest level of the most recent Action right target to practice. // ' Its goal is the expectation. That is what is being predicted. // ' If the interest / concentration level is familiar then use thinking to search for something // ' more interesting to do // ' end if // 'end if // // ' If was practicing - failed or matched will have no AttendTo and Expected = goal set, PracticingBinon = NullObject // ' - repeating trigger or goal and not interrupted then PracticingBinon will be set // ' If not practicing AttendTo is not set, PracticingBinon = NullObject and ExpectedBinon = NullObject // ' 10a. THINKING: // ' If still no Action worth practicing then find one through thinking. // ' Find an Action that will lead to one that needs practicing or that will produce a // ' rewarding final goal stimulus. // ' Pay attention to the goal stimulus of the most recent Action of the attended-to stimulus and // ' treat it as though it was the attended-to stimulus and repeat steps 8 and 9 above. // ' This is thinking of the goal by traversing the Actions for this stimulus as the trigger. // ' This repeats until we come across an Action that has a desirable redo interest or // ' a pleasant expected goal stimulus. // ' There will be a limit on this looping to begin with. Some other criterion is required // ' to stop this thinking. It must stop if it loops around to an already thought about Action. // ' If it is successful the first thought about Action will be selected for performing in step 11 // ' as the active practicing Action at the appropriate concentration level. // ' In a real-time system a thinking loop may continue until it is interrupted by an unexpected stimulus. // ' Should the thinking loop also select additional Actions or should they only be started by a conscious stimulus? // ' Where does boredom fit in - results from repetition of a conscious stimulus? // ' Or if we have a limited number of thinking steps we may not find an Action worth doing. // ' Should thinking be done after or before investigating the parts of the attended-to in step 9? // ' Thinking is based on recalling the goal stimulus of the most recent Action // ' for the attended-to stimulus and letting the interest in this goal stimulus determine whether to // ' perform the Action. Should we store the thought as a thought so that it can be repeated // ' if successful and learnt? // ' We are bored when the only Action we have to do is a familiar one or there is no Action to do. // ' If we get the expected goal of a familiar Action then the sequence is the next trigger. // // ' Also might consider the situation where do have a conscious active Action but it is being done at the // ' interesting level and thinking produces a novel one to practice - if this is logically possible. } // End of DetermineResponse() public class Bodies { // // Called to assign the different body configuration parameters // Called to perform each sense/response action cycle by World.Go_Click() // // // World data moved here because it can't be put in World form // The positions of the world as appearing String[][] WP = new String[40 + 1][40 + 1]; // in the Current World grid, a ABlock$ = "#" indicates // the location is a blacked out square // Label NG(0 To 383) // Number Grid is stored in linear array of Labels NG(0) to NG(383) // that have no borders. These contain the location letters that can be displayed. // Label CWP(0 To 511) // World Grid is stored in linear array of Labels CWP(0)->CWP(511) // that have borders and can contain letters. The background colour is black for a block and light blue // for the cursor. The CWP.Caption = "S" for where Smarty is. String MaxBodies; String BExternal; int InputSense; void BodyAssignStimuli() { // Fills in the Values$() with KIN$() from last response int Sens; var Stimuli = new Var<>(""); // Public NumSenses 'The number of physical senses, Max of 8, set in SetUpSense() // 'Currently equals the NumProperties since each sense currently = 1 property type // Public MaxSenses 'Maximum number of senses = max 8 physical senses // Public Sense$(1 To 8) 'Names of senses, up to 8 physical senses // Public IsSense '1, Flag for Senses versus Devices // // Public Senses(1 To 8, 1 To 8) 'Properties of the different senses // '1st index = Sense number // '2nd index = Sense property // // '---- Senses() - 2nd index values - Sense Properties // Public PropertyBinonType '1, Stimulus property binon type e.g. 1 = TextBin or 2 = ContBin // Public SymbolicOrMagnitude '2, Symbolic or Magnitude indicator // Public LowerRangeLimit '3, Lower limit of range of values, zero is minimum (65 = "A") // Public UpperRangeLimit '4, Upper limit of range of values, 255 is maximum (90 ="Z") // Public LinearOrCircular '5, Linear list or Ring/Circular of values for Magnitude sense, Distance is Linear, Compass degrees are Circular (0 to 360) // Public IntegersOrLogs '6, Integer Values or Log Values, Temperatures are Integers while Decibels are Logs // Public NumberOfSensors '7 Number of sensors in sensor array // Public SensorsDependentOrIndependent '8 are sensors adjacent (dependent) or independent // Public SensorValues[1 To 8][1 To 2][0 To 1] 'Stimulus values from senses/sensors // '1st index is sense number, currently = property binon type // '2nd index is what type of information is in the SensorValues(), XQCnt or Valu // '3rd index is Fired for the most recent stimulus value and Current for the previous // // '---- SensorValues 2nd index values - type of information in SensorValues() // Public XQCnt '=1, the count of times the value has repeated, also used below // Public Valu '=2, the value for the stimulus, if symbolic then value = Asc(Symbol$) // Public NoName$ '"_", The character used when no letter provided for the IDL value of a TextBin binon // // '---- SensorValues 3rd index values - which past stimulus it is - also used below // Public Fired '=0 'stimulus put in this level upon firing before being processed // Public Current '=1 'The Fired one becomes the Current one after processing LIN = LIN + 1; for (// For each sense Sens = 1; // For each sense Sens <= NumSenses; // For each sense Sens++) { ping(); if (Senses[Sens][SymbolicOrMagnitude] == Magnitude) { // get the stimuli from body senses GetStimuli(Sens, Stimuli); // Stimuli$ = Chr$(of the range to far wall) SensorValues[Sens][XQCnt][Fired] = 1; // one character per sense SensorValues[Sens][Valu][Fired] = asc(Stimuli.get()); // convert to "1" to "8" INPUTS[LIN][Sens] = chr(SensorValues[Sens][Valu][Fired] + 48); } else // Else Symbolic input { // Setup a motion sense if WheelsConfig.AddAWheelSensor = 1 is checked if (// If its name is the sense of motion then Sense[Sens].equals("Motion")) { SensorValues[Sens][XQCnt][Fired] = 1; SensorValues[Sens][Valu][Fired] = asc(Motion); } else // else it is some other symbolic sense { // get the stimuli from body senses GetStimuli(Sens, Stimuli); SensorValues[Sens][XQCnt][Fired] = 1; // one character per sense SensorValues[Sens][Valu][Fired] = asc(Stimuli.get()); } INPUTS[LIN][Sens] = chr(SensorValues[Sens][Valu][Fired]); } } } // End of BodyAssignStimuli() public final // called from World.Go to perform a cycle void BodyFunction2() { // This routine determines the current stimuli and changes the body's state // based on which body is currently being used. String CurrentPlace = null; char Kn; char Resp; // Smarty0$ body has a sensor that looks under at the current square and // moves Up, Down, Left or Right. Always displayed as an O // If a body can turn and change the direction it is pointing // then it is displayed as an ^, >, <, or v CurrentPlace = World.LookUnder(); // Public DeviceValues(1 To 8, 1 To 2) 'Response values for devices // '1st index is device number, currently = response property binon type // '2nd index is what type of information is in the DeviceValues(), XQCnt or Valu // // '---- DeviceValues 2nd index values - type of information in DeviceValues() - DEFINED ABOVE // ' Public XQCnt '=1, the count of times the value needs repeating, also used below // ' Public Valu '=2, the value for the response, if symbolic then Symbol$ = Chr$(value) // Public NoResp$ '"-", The character representing no response for a LetrBin binon // fills in the Values$() from the senses and BodyAssignStimuli(); // the Motion$ from last response if turned on PerceptionAction(SensorValues, DeviceValues); if (NumDevices > 1) { Stop(); } Resp = (char) DeviceValues[1][Valu]; Kn = Resp; switch(// Motion$ will be set by the World.Move routines Resp) { case NoResp: // = Mid$(WheelMovement$, 1, 1) Motion = NoMove; break; case MoveForward: switch(BodyPointing) { case East: World.MoveEast(); break; case South: World.MoveSouth(); break; case West: World.MoveWest(); break; case North: World.MoveNorth(); break; } if (Motion.equals("Y")) { Motion = WheelMovement.substring(1, 2); } break; case MoveToLeft: switch(BodyPointing) { case East: World.MoveNorth(); break; case South: World.MoveEast(); break; case West: World.MoveSouth(); break; case North: World.MoveWest(); break; } if (Motion.equals("Y")) { Motion = WheelMovement.substring(2, 3); } break; case MoveToRight: switch(BodyPointing) { case East: World.MoveSouth(); break; case South: World.MoveWest(); break; case West: World.MoveNorth(); break; case North: World.MoveEast(); break; } // WheelMovement$ = "-flrb" & rotate left, right and around 180 degrees if (Motion.equals("Y")) { Motion = WheelMovement.substring(3, 4); } break; case MoveBackward: switch(BodyPointing) { case East: World.MoveWest(); break; case South: World.MoveNorth(); break; case West: World.MoveEast(); break; case North: World.MoveSouth(); break; } if (Motion.equals("Y")) { Motion = WheelMovement.substring(4, 5); } break; case // rotate right 90 degrees TurnRght: BodyPointing = BodyPointing + 1; if (BodyPointing == 4) { BodyPointing = 0; } // a rotate always happens Motion = WheelMovement.substring(5, 6); break; case // rotate left 90 dgrees TurnLft: BodyPointing = BodyPointing - 1; if (BodyPointing == -1) { BodyPointing = 3; } // a rotate always happens Motion = WheelMovement.substring(6, 7); break; case // rotate around 180 degrees TurnArnd: BodyPointing = BodyPointing + 2; if (BodyPointing == 4) { BodyPointing = 0; } if (BodyPointing == 5) { BodyPointing = 1; } // a rotate always happens Motion = WheelMovement.substring(7, 8); break; } // Case Resp$ // Orient body pointer on world view if wheels turn if (WheelsTurn) { switch(// direction body is pointing, 0=East, 1=South, 2=West, 3=North BodyPointing) { case East: // > World.PointEast(); break; case South: // v World.PointSouth(); break; case West: // < World.PointWest(); break; case North: // ^ World.PointNorth(); // Case 4 // Call World.RangeSymbol ' "+" sign break; } } else // else the wheels don't turn so display an A { // "A" = Adaptron pointing North World.PointUnder(); } // for HistoryDisplay of outputs OUTPUTS[LIN][1] = OUTPUTS[LIN][1] + Kn; // persist any changes in this object change(); // dump all the history and LTMem() World.Update_View(); // do this for each sense // fillin the World.VB() value World.DisplayStimuliAndResponse(SensorValues, Resp); } // End of BodyFunction2() public final void GetStimuli(int Sens, Var ReturnedStimuli) { // Get the stimulus value for each Sens. // Currently each Sense is a single sensor ReturnedStimuli.set(""); if (Senses[Sens][SymbolicOrMagnitude] == Magnitude) { switch(// Based on the name of the sense Sense[Sens]) { case // Looking down at cell - distance 1 cell away "VisionD": ReturnedStimuli.set(ReturnedStimuli.get() + (char) 1); break; case // looking left based on body direction "VisionL": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeWest())); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeNorth())); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeEast())); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeSouth())); break; } break; case // looking right "VisionR": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeEast())); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeSouth())); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeWest())); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeNorth())); break; } break; case // looking forward "VisionF": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeNorth())); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeEast())); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeSouth())); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeWest())); break; } break; case // looking behind "VisionB": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeSouth())); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeWest())); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeNorth())); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + chr(World.RangeEast())); break; } break; } } else // Sense is symbolic { if (// If vision just looking at next square then Senses[Sens][LowerRangeLimit] == asc(Wall)) { switch(// Based on the name of the sense Sense[Sens]) { case // Looking down at cell floor "VisionD": ReturnedStimuli.set(Wall); break; case // looking left based on body direction "VisionL": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest()); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth()); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast()); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth()); break; } break; case // looking right "VisionR": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast()); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth()); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest()); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth()); break; } break; case // looking forward "VisionF": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth()); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast()); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth()); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest()); break; } break; case // looking behind "VisionB": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth()); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest()); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth()); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast()); break; } break; } if (// if it's not a wall then the square is empty !ReturnedStimuli.get().equals(Wall)) { ReturnedStimuli.set(EmptySquare); } } else // Else vision looking at symbolic location value in next square { switch(// Based on the name of the sense Sense[Sens]) { case // Looking down at cell "VisionD": ReturnedStimuli.set(ReturnedStimuli.get() + World.LookUnder()); break; case // looking left based on body direction "VisionL": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest()); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth()); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast()); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth()); break; } break; case // looking right "VisionR": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast()); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth()); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest()); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth()); break; } break; case // looking forward "VisionF": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth()); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast()); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth()); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest()); break; } break; case // looking behind "VisionB": switch(BodyPointing) { case North: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookSouth()); break; case East: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookWest()); break; case South: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookNorth()); break; case West: ReturnedStimuli.set(ReturnedStimuli.get() + World.LookEast()); break; } break; } } // end if its looking for wall or space or looking for square location letter } // end if sense is magnitude or symbolic } // End of GetStimuli() } } // end of Smarty static final class StringHelper { // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'Substring' when 'start' is a method // call or calculated value to ensure that 'start' is obtained just once. // ------------------------------------------------------------------------------------ public static String substring(String string, int start, int length) { if (length < 0) throw new IndexOutOfBoundsException("Parameter length cannot be negative."); return string.substring(start, start + length); } // ------------------------------------------------------------------------------------ // This method replaces the .NET static string method 'IsNullOrEmpty'. // ------------------------------------------------------------------------------------ public static boolean isNullOrEmpty(String string) { return string == null || string.length() == 0; } // ------------------------------------------------------------------------------------ // This method replaces the .NET static string method 'IsNullOrWhiteSpace'. // ------------------------------------------------------------------------------------ public static boolean isNullOrWhiteSpace(String string) { if (string == null) return true; for (int index = 0; index < string.length(); index++) { ping(); if (!Character.isWhitespace(string.charAt(index))) return false; } return true; } // ------------------------------------------------------------------------------------ // This method replaces the .NET static string method 'Join' (2 parameter version). // ------------------------------------------------------------------------------------ public static String join(String separator, String[] stringArray) { if (stringArray == null) return null; else return join(separator, stringArray, 0, stringArray.length); } // ------------------------------------------------------------------------------------ // This method replaces the .NET static string method 'Join' (4 parameter version). // ------------------------------------------------------------------------------------ public static String join(String separator, String[] stringArray, int startIndex, int count) { if (stringArray == null) return null; StringBuilder sb = new StringBuilder(); for (int index = startIndex; index < stringArray.length && index - startIndex < count; index++) { ping(); if (separator != null && index > startIndex) sb.append(separator); if (stringArray[index] != null) sb.append(stringArray[index]); } return sb.toString(); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'Remove' (1 parameter version). // ------------------------------------------------------------------------------------ public static String remove(String string, int start) { return string.substring(0, start); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'Remove' (2 parameter version). // ------------------------------------------------------------------------------------ public static String remove(String string, int start, int count) { return string.substring(0, start) + string.substring(start + count); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'TrimEnd'. // ------------------------------------------------------------------------------------ public static String trimEnd(String string, Character... charsToTrim) { if (string == null || charsToTrim == null) return string; int lengthToKeep = string.length(); for (int index = string.length() - 1; index >= 0; index--) { ping(); boolean removeChar = false; if (charsToTrim.length == 0) { if (Character.isWhitespace(string.charAt(index))) { lengthToKeep = index; removeChar = true; } } else { for (int trimCharIndex = 0; trimCharIndex < charsToTrim.length; trimCharIndex++) { ping(); if (string.charAt(index) == charsToTrim[trimCharIndex]) { lengthToKeep = index; removeChar = true; break; } } } if (!removeChar) break; } return string.substring(0, lengthToKeep); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'TrimStart'. // ------------------------------------------------------------------------------------ public static String trimStart(String string, Character... charsToTrim) { if (string == null || charsToTrim == null) return string; int startingIndex = 0; for (int index = 0; index < string.length(); index++) { ping(); boolean removeChar = false; if (charsToTrim.length == 0) { if (Character.isWhitespace(string.charAt(index))) { startingIndex = index + 1; removeChar = true; } } else { for (int trimCharIndex = 0; trimCharIndex < charsToTrim.length; trimCharIndex++) { ping(); if (string.charAt(index) == charsToTrim[trimCharIndex]) { startingIndex = index + 1; removeChar = true; break; } } } if (!removeChar) break; } return string.substring(startingIndex); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'Trim' when arguments are used. // ------------------------------------------------------------------------------------ public static String trim(String string, Character... charsToTrim) { return trimEnd(trimStart(string, charsToTrim), charsToTrim); } // ------------------------------------------------------------------------------------ // This method is used for string equality comparisons when the option // 'Use helper 'stringsEqual' method to handle null strings' is selected // (The Java String 'equals' method can't be called on a null instance). // ------------------------------------------------------------------------------------ public static boolean stringsEqual(String s1, String s2) { if (s1 == null && s2 == null) return true; else return s1 != null && s1.equals(s2); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'PadRight' (1 parameter version). // ------------------------------------------------------------------------------------ public static String padRight(String string, int totalWidth) { return padRight(string, totalWidth, ' '); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'PadRight' (2 parameter version). // ------------------------------------------------------------------------------------ public static String padRight(String string, int totalWidth, char paddingChar) { StringBuilder sb = new StringBuilder(string); while (sb.length() < totalWidth) { ping(); sb.append(paddingChar); } return sb.toString(); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'PadLeft' (1 parameter version). // ------------------------------------------------------------------------------------ public static String padLeft(String string, int totalWidth) { return padLeft(string, totalWidth, ' '); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'PadLeft' (2 parameter version). // ------------------------------------------------------------------------------------ public static String padLeft(String string, int totalWidth, char paddingChar) { StringBuilder sb = new StringBuilder(); while (sb.length() + string.length() < totalWidth) { ping(); sb.append(paddingChar); } sb.append(string); return sb.toString(); } // ------------------------------------------------------------------------------------ // This method replaces the .NET string constructor which repeats a character. // ------------------------------------------------------------------------------------ public static String repeatChar(char charToRepeat, int count) { String newString = ""; for (int i = 1; i <= count; i++) { ping(); newString += charToRepeat; } return newString; } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'LastIndexOf' (char version). // ------------------------------------------------------------------------------------ public static int lastIndexOf(String string, char value, int startIndex, int count) { int leftMost = startIndex + 1 - count; int rightMost = startIndex + 1; String substring = string.substring(leftMost, rightMost); int lastIndexInSubstring = substring.lastIndexOf(value); if (lastIndexInSubstring < 0) return -1; else return lastIndexInSubstring + leftMost; } // ------------------------------------------------------------------------------------ // This method replaces the .NET string method 'LastIndexOf' (string version). // ------------------------------------------------------------------------------------ public static int lastIndexOf(String string, String value, int startIndex, int count) { int leftMost = startIndex + 1 - count; int rightMost = startIndex + 1; String substring = string.substring(leftMost, rightMost); int lastIndexInSubstring = substring.lastIndexOf(value); if (lastIndexInSubstring < 0) return -1; else return lastIndexInSubstring + leftMost; } } static final class FloatingPointToInteger { public static byte ToSByte(double source) { byte floor = (byte) Math.floor(source); if (Math.abs(source - floor) == 0.5) { if (floor % 2 == 0) return floor; else return (byte) Math.ceil(source); } else if (Math.abs(source - floor) < 0.5) return floor; else return (byte) Math.ceil(source); } public static short ToInt16(double source) { short floor = (short) Math.floor(source); if (Math.abs(source - floor) == 0.5) { if (floor % 2 == 0) return floor; else return (short) Math.ceil(source); } else if (Math.abs(source - floor) < 0.5) return floor; else return (short) Math.ceil(source); } public static int ToInt32(double source) { int floor = (int) Math.floor(source); if (Math.abs(source - floor) == 0.5) { if (floor % 2 == 0) return floor; else return (int) Math.ceil(source); } else if (Math.abs(source - floor) < 0.5) return floor; else return (int) Math.ceil(source); } public static long ToInt64(double source) { long floor = (long) Math.floor(source); if (Math.abs(source - floor) == 0.5) { if (floor % 2 == 0) return floor; else return (long) Math.ceil(source); } else if (Math.abs(source - floor) < 0.5) return floor; else return (long) Math.ceil(source); } } // debug sensor output static boolean debugValues = false; static int defaultSpacing = 10, spacing; static JFrame mainFrame; static List> gridComponents; static JComponent mainGrid; static JCheckBoxMenuItem miShowLocations; static SingleComponentPanel scpMainGrid, scpVisionConfig, scpWheelsConfig, scpCurrentSmarty, scpStimuliAndResponse; static JFrame historyFrame, memoryFrame; static JSpinner worldSizeSpinner; static JTextArea historyTextArea1, historyTextArea2; static JTextArea taSensorValues, taDeviceValues; // originally: BinonDisplay.ObjList.Text static JTextArea memoryTextArea1; // originally: BinonDisplay.ChngResults.Text static JTextArea memoryTextArea2; // AI instance static Smarty smarty; // queue for Smarty operations static Q smartyQ = startQ("Smarty Q"); static String wallSymbol = unicode_blackSquare(), noWallSymbol = unicode_dottedSquare(); static Color lightBlue = colorFromHex("4169e1"); static String locationLetters = charRange('A', 'Z') + "[\\]^_`" + charRange('a', 'z') + charRange(123, 128); static String smartyUnicode = unicode_slightlySmilingFace(); static int smartyFontSize = 40; static String windowsFontID = "#1400468"; static String emojiFontID = "#1400470"; static String frameIconID = "#1102983"; static String monospacedFontID = /*#1400479*/ "#1400483"; static double monospacedFontSize = 12; static boolean smartyBrainPersistence = false; static String smartyImageID = "#1102987"; static String helpTextID = "#1031105"; static String worldFileExtension = "WLD"; static String bodyFileExtension = "BDY"; static String historyHelp = unindent_mls("\r\n A percept is the stimulus or simultaneous combination of stimuli observed.\r\n An action is the response or simultaneous combination of responses produced.\r\n Binon # numbers refer to the binons in memory that represent the percepts, actions, expectations, and perceptual or action sequences.\r\n P = Percept, E = Expectation, PP = Perceptual sequence A = Action, AA = Action sequence\r\n Read the paper: \"The Perception-Action Hierarchy and its Implementation Using Binons (Binary Neurons)\" on the www.adaptroninc.com website for more information.\r\n"); // translate Smarty's windows characters to unicode static Map winToUnicode = litmap(Smarty.Smarty, unicode_slightlySmilingFace(), Smarty.UpArrow, unicode("2191"), Smarty.LeftArrow, unicode("2190"), Smarty.RightArrow, unicode("2192"), Smarty.DownArrow, unicode("2193"), Smarty.Wall, unicode_blackVerticalRectangle(), Smarty.EmptySquare, unicode_whiteVerticalRectangle(), Smarty.chr(Smarty.TurnRght), unicode("21B1"), Smarty.chr(Smarty.TurnLft), unicode("21B0"), Smarty.chr(Smarty.TurnArnd), unicode("21B7"), Smarty.chr(254), unicode_blackSmallSquare()); static boolean showTabs = true; static int defaultWorldSize = 7, maxWorldSize = 8; static ReliableSingleThread rstUpdateChngResults = rstWithPreDelay(250, new Runnable() { public void run() { try { setText(memoryTextArea2, winToUnicode(state.binonDisplayChngResults)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "setText(memoryTextArea2, winToUnicode(state.binonDisplayChngResults));"; } }); static void rearrangeLetters() { int iLetter = 0; for (int y = 0; y < state.gridRows; y++) for (int x = 0; x < state.gridCols; x++) { JCell cell = getCell(x, y); if (cell.obstacle()) cell.letter = ' '; else cell.letter = locationLetters.charAt(iLetter++); } } static class VisionMode { static String nextSquare = "next square"; static String distanceToWall = "distance to wall"; static String wallOrNot = "wall or not"; } static class CameraDirection { static String down = "down"; static String left = "left"; static String right = "right"; static String inFront = "in front"; static String behind = "behind"; static List all = ll(down, left, right, inFront, behind); } static class SmartyBody extends Concept { static final String _fieldOrder = "name cameraDirections visionMode wheels changed used"; String name = "Smarty0"; Set cameraDirections = litset(CameraDirection.down); // see VisionMode String visionMode = VisionMode.nextSquare; Set wheels = litset("MoveForward", "MoveLeft", "MoveRight", "MoveBackward"); // changed w.r.t. file boolean changed = false; // used in Smarty execution boolean used = false; // for saving String wheelsFlag(String flag) { return wheels.contains(flag) ? "1" : "0"; } void userCausedChange() { print("Body: User caused change"); changed = true; change(); } } static class State extends Concept { static final String _fieldOrder = "fontScale worldName gridRows gridCols showLocations worldChanged startX startY smartyX smartyY smartyDirection selection cursorDirection obstacles history1 history2 memory1 sensorValuesText deviceValuesText binonDisplayChngResults body recentWorldFiles recentBodyFiles"; float fontScale = 1.5f; String worldName = "Empty"; // actually these are always identical, could merge into one int gridRows = defaultWorldSize, gridCols = defaultWorldSize; boolean showLocations = false; boolean worldChanged = false; // Smarty's start position int startX, startY; int smartyX, smartyY; // which way Smarty is looking - this or smarty.LeftArrow etc. String smartyDirection = Smarty.Smarty; Rect selection = rect(1, 1, 1, 1); Pt cursorDirection = pt(1, 0); BitSet obstacles = new BitSet(); String history1 = "", history2 = "", memory1 = "", sensorValuesText = "", deviceValuesText = ""; // memory2 String binonDisplayChngResults = ""; Ref body = new Ref(); // value is just true Map recentWorldFiles = synchronizedMRUCache(5); Map recentBodyFiles = synchronizedMRUCache(5); void setSelection(Rect r) { if (!cset_trueIfChanged(this, "selection", r)) return; if (selection.h == 1 && selection.w > 1) _setField("cursorDirection", pt(1, 0)); else if (selection.w == 1 && selection.h > 1) _setField("cursorDirection", pt(0, 1)); repaintGrid(); } void clearSelectedArea() { fillSelection(false); } void invertSelection() { JCell cell1 = getCell(selection.x, selection.y); fillSelection(!cell1.obstacle()); } void fillSelection(boolean b) { for (Pt p : pointsInRect(selection)) if (// don't put an obstacle over Smarty !(b && state.smartyX == p.x && state.smartyY == p.y)) getCell(p.x, p.y).setObstacle(b); rearrangeLetters(); moveCursor(); } void moveCursor() { setCursor(selection.x + cursorDirection.x, selection.y + cursorDirection.y); } void setCursor(int x, int y) { setSelection(rect(mod(x, gridCols), mod(y, gridRows), 1, 1)); } void moveCursor(int dx, int dy) { _setField("cursorDirection", pt(dx, dy)); setCursor(selection.x + cursorDirection.x, selection.y + cursorDirection.y); } void placeSmarty() { getCell(selection.x, selection.y).setObstacle(false); cset(state, "startX", selection.x, "startY", selection.y); moveSmarty(selection.x, selection.y); moveCursor(); } void moveSmarty(int x, int y) { if (!inRange(x, 0, gridCols) || !inRange(y, 0, gridRows)) throw fail("Smarty position not in range: " + x + "/" + y); if (cset_trueIfChanged(this, "smartyX", x, "smartyY", y)) { cset(this, "worldChanged", true); repaintGrid(); } } void moveSmartyRelative(int x, int y) { moveSmarty(smartyX + x, smartyY + y); } } // end of State static State state; static class JCell extends JComponent { int x, y; char letter; JCell(int x, int y) { this.y = y; this.x = x; } public void paint(Graphics _g) { Graphics2D g = (Graphics2D) _g; int w = getWidth(), h = getHeight(); Color color = Color.white; if (state.selection.contains(x, y)) color = lightBlue; else if (obstacle()) color = Color.black; fillRect(g, 0, 0, w, h, color); if (state.showLocations && !obstacle()) { AutoCloseable __17 = tempSetFont(g, loadFont_cached(windowsFontID)); try { drawTextWithTopLeftCornerAt(g, str(letter), new Pt(2, 0), Color.black); } finally { _close(__17); } } if (state.smartyX == x && state.smartyY == y) { AutoCloseable __18 = tempSetFontSize(g, smartyFontSize); try { /*temp tempSetFont(g, loadFont_cached(emojiFontID)); drawCenteredText(g, smartyUnicode, 0, 0, w, h, Color.black);*/ double size = 0.6; int dx = iround((1 - size) / 2 * w); int dy = iround((1 - size) / 2 * h); if (eq(state.smartyDirection, smarty.Smarty)) drawScaledImage(g, loadImage2_cached(smartyImageID), rectFromPoints(dx, dy, w - dx, h - dy)); else { // temp tempSetFont(g, loadFont_cached(windowsFontID)); String icon = lookupOrKeep(winToUnicode, state.smartyDirection); drawCenteredText(g, icon, 0, 0, w, h, Color.black); } } finally { _close(__18); } } } int index() { return y * state.gridCols + x; } boolean obstacle() { return main.contains(state.obstacles, index()); } void setObstacle(boolean b) { if (setBit_trueIfChanged(state.obstacles, index(), b)) { cset(state, "worldChanged", true); state.change(); } } { addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { main.requestFocus(mainGrid); if (!isLeftButton(e)) return; state.setSelection(new Rect(x, y, 1, 1)); } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent e) { // _print("Drag in " + x + "/" + y + ": " + e.getPoint()); Component dest = componentAtScreenLocationInWindow(mainFrame, e); if (dest instanceof JCell) { // _print("Target: " + dest); state.setSelection(rectFromPointsInclusiveSorted(x, y, ((JCell) dest).x, ((JCell) dest).y)); } } }); } public String toString() { return x + "/" + y; } } static JCell getCell(int x, int y) { return gridComponents.get(y).get(x); } static JCell smartyCell() { return getCell(state.smartyX, state.smartyY); } static boolean inGrid(int x, int y) { return inRange(y, state.gridRows) && inRange(x, state.gridCols); } static void makeMainGrid() { gridComponents = map(iotaZeroList(state.gridRows), y -> map(iotaZeroList(state.gridCols), x -> new JCell(x, y))); mainGrid = setFocusable(setBackground(Color.black, hvgrid(gridComponents, 1))); scpMainGrid.setComponent(mainGrid); rearrangeLetters(); } // always clears the world static void setWorldSize(int size) { state.obstacles.clear(); state.gridCols = state.gridRows = size; setSpinnerValue(worldSizeSpinner, size); state.selection = rect(1, 1); cset(state, "startX", 0, "startY", 0); state.moveSmarty(0, 0); cset(state, "worldChanged", false); state.change(); makeMainGrid(); resetSmarty(); } static void repaintGrid() { repaint(mainGrid); } // add more functions here public static void main(final String[] args) throws Exception { smartyMain(); } static void smartyMain() { System.out.println("Main class: " + strWithIdentityHashCode(mc()) + ", class loader: " + getClassLoader(mc())); autoRestart(2.0); // print all vm bus msgs from concepts // vmBus_snoopToPrint((msg, arg) -> firstOfArrayOrSame(arg) instanceof Concepts); setProgramDir(print("Using directory: ", mainDir())); logProgramOutput(); _handleException_showThreadCancellations = true; if (!isDevVersion()) hideConsole(); else veryBigConsole(); db(); // make at least one instance uniq(SmartyBody.class); state = uniq(State.class); smarty = uniq(Smarty.class); initSmarty(); // default body if (!state.body.has()) cset(state, "body", conceptWhere(SmartyBody.class)); // cset(state.body, used := false); // XXX // prep GUI // styling jtattoo_mcWin(); // set swingFontScale_debug; // scaling updateFontScale(state.fontScale); // no space bar for buttons disableSpaceBarForAllButtons(); loadLibrary(windowsFontID); defaultFrameIcon(frameIconID); mainFrame = showFrame("Smarty"); // exitOnClose(mainFrame); onWindowClosing(mainFrame, runnableThread(new Runnable() { public void run() { try { // proper clean-up for standalone mode cleanUp(mc()); cleanKillVM(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cleanUp(mc()); // proper clean-up for standalone mode\r\n cleanKillVM();"; } })); historyTextArea1 = monospaced(uneditableBlackTextArea_noUndo()); historyTextArea2 = monospaced(uneditableBlackTextArea_noUndo()); memoryTextArea1 = /*withTypeWriterFont*/ monospaced(uneditableBlack(swing(() -> new JLineHeightTextArea(0.8)))); memoryTextArea2 = monospaced(uneditableBlackTextArea_noUndo(winToUnicode(state.binonDisplayChngResults))); makeMenus(); registerCtrlKey(mainFrame, KeyEvent.VK_N, "New world", new Runnable() { public void run() { try { print("new"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "print(\"new\")"; } }); registerCtrlKey(mainFrame, KeyEvent.VK_R, "Retrieve world", new Runnable() { public void run() { try { ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return ""; } }); registerCtrlKey(mainFrame, KeyEvent.VK_S, "Save world", new Runnable() { public void run() { try { ; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return ""; } }); addMenu(mainFrame, "View", miShowLocations = jCheckBoxMenuItem("Locations (Ctrl+L)", state.showLocations, b -> { cset(state, "showLocations", b); repaintGrid(); }), jMenu("UI Zoom", "100%", new Runnable() { public void run() { try { uiZoom(100); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "uiZoom(100)"; } }, "112%", new Runnable() { public void run() { try { uiZoom(112); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "uiZoom(112)"; } }, "125%", new Runnable() { public void run() { try { uiZoom(125); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "uiZoom(125)"; } }, "140%", new Runnable() { public void run() { try { uiZoom(140); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "uiZoom(140)"; } }), "---", "Self-Test", runnableThread(new Runnable() { public void run() { try { selfTest(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "selfTest();"; } }), "Console", new Runnable() { public void run() { try { activateConsole(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "activateConsole();"; } }); registerCtrlKey(mainFrame, KeyEvent.VK_L, "Locations", new Runnable() { public void run() { try { cset(state, "showLocations", !state.showLocations); setChecked(miShowLocations, state.showLocations); repaintGrid(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cset(state, showLocations := !state.showLocations);\r\n setChecked(miShowL..."; } }); JMenuBar menuBar = getMenuBar(mainFrame); JMenuItem helpItem = jMenuItem("Help F1", runnableThread(new Runnable() { public void run() { try { showHelp(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showHelp();"; } })); /*print(minSize := getMinimumSize(helpItem)); print(preferredSize := getPreferredSize(helpItem));*/ addMenuItem(menuBar, jPreferredWidthToMaxWidth(helpItem)); // spacer addAndRevalidate(menuBar, jHorizontalGlue()); registerFunctionKey(mainFrame, 1, runnableThread(new Runnable() { public void run() { try { showHelp(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showHelp();"; } })); registerKeyCode(mainFrame, KeyEvent.VK_SPACE, new Runnable() { public void run() { try { state.invertSelection(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.invertSelection()"; } }); registerKeyCode(mainFrame, KeyEvent.VK_UP, new Runnable() { public void run() { try { state.moveCursor(0, -1); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.moveCursor(0, -1)"; } }); registerKeyCode(mainFrame, KeyEvent.VK_LEFT, new Runnable() { public void run() { try { state.moveCursor(-1, 0); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.moveCursor(-1, 0)"; } }); registerKeyCode(mainFrame, KeyEvent.VK_DOWN, new Runnable() { public void run() { try { state.moveCursor(0, 1); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.moveCursor(0, 1)"; } }); registerKeyCode(mainFrame, KeyEvent.VK_RIGHT, new Runnable() { public void run() { try { state.moveCursor(1, 0); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.moveCursor(1, 0)"; } }); // react to any letter from A to Z for (int key = KeyEvent.VK_A; key <= KeyEvent.VK_Z; key++) registerKeyCode(mainFrame, key, new Runnable() { public void run() { try { state.placeSmarty(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.placeSmarty()"; } }); worldSizeSpinner = jSpinner(state.gridCols, 1, maxWorldSize); onChange(worldSizeSpinner, new Runnable() { public void run() { try { int size = intFromSpinner(worldSizeSpinner); if (state.gridCols != size) { if (state.worldChanged) { int result = swingShowConfirmDialog(mainFrame, "World has changed! - Save it before resizing?", "Smarty", JOptionPane.YES_NO_CANCEL_OPTION); if (result == JOptionPane.YES_OPTION) { saveWorldDialog(new Runnable() { public void run() { try { newWorldWithoutConfirmation(size); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newWorldWithoutConfirmation(size)"; } }); return; } else if (result == JOptionPane.CANCEL_OPTION) { setSpinnerValue(worldSizeSpinner, state.gridCols); return; } } newWorldWithoutConfirmation(size); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "int size = intFromSpinner(worldSizeSpinner);\r\n if (state.gridCols != size)..."; } }); scpCurrentSmarty = singleComponentPanel(); JComponent middleArea = westAndCenterWithMargin(spacing, jvstackWithSpacing(spacing, withTitle(("World size (max=" + maxWorldSize + ")"), worldSizeSpinner), jbutton("Clear Selected Area", runnableThread(new Runnable() { public void run() { try { state.clearSelectedArea(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "state.clearSelectedArea()"; } })), withTitle("Current world", disableTextField(jLiveValueTextField(conceptFieldLiveValue("worldName", state)))), showTabs ? null : fontSizePlus(2, setForeground(Color.ORANGE, jCenteredLabel("Design or Select a body for Smarty"))), showTabs ? null : jbutton("Design or Select Smarty's Body", new Runnable() { public void run() { try { showSmartyConfig(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showSmartyConfig();"; } }), withTitle("Current Smarty", scpCurrentSmarty)), jvgridWithSpacing(spacing, withTitle(monospaced(jLabel("Sensors: Values: are:")), taSensorValues = monospaced(uneditableBlackTextArea_noUndo())), withTitle(monospaced(jLabel("Devices: Values: are:")), taDeviceValues = monospaced(uneditableBlackTextArea_noUndo())))); JComponent controlArea = northAndCenterWithMargin(spacing, vstackWithSpacing(fontSizePlus(2, setForeground(Color.blue, jlabel("Design the World - Read the Help F1"))), jMinHeight(swingScale(200), middleArea)), jCenteredSection("Run Smarty", jflow(jbutton("Go / Continue", runnableThread(new Runnable() { public void run() { try { goCmd(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "goCmd();"; } })), jButton("See History", new Runnable() { public void run() { try { showHistory(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showHistory();"; } }), jbutton("See Memory", new Runnable() { public void run() { try { showMemory(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showMemory();"; } }), jbutton("Reset", new Runnable() { public void run() { try { resetSmarty(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "resetSmarty();"; } }), jbutton("EXIT", runnableThread(new Runnable() { public void run() { try { killVM(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "killVM();"; } }))))); scpMainGrid = singleComponentPanel(); makeMainGrid(); var mainPanel = westAndCenterWithMargins(spacing, jvstackWithSpacing(spacing, jFixedSize(500, scpMainGrid), scpStimuliAndResponse = singleComponentPanel()), controlArea); if (showTabs) { scpVisionConfig = singleComponentPanel(); scpWheelsConfig = singleComponentPanel(); updateTabs(); setFrameContents(mainFrame, jtabs("Smarty", mainPanel, "Vision", scpVisionConfig, "Wheels", scpWheelsConfig)); } else setFrameContents(mainFrame, mainPanel); centerPackFrame(mainFrame); // set minimum width jMinWidth_pure(mainFrame, max(1000, swingScale(800))); centerFrameWithMinWidth(mainFrame); // set min frame height jMinHeight_pure(mainFrame, getHeight(mainFrame)); // disable height changes entirely (not good, may cut off at the bottom) // frameMaxHeight(mainFrame, getHeight(mainFrame)); // smarty.World.Update_View(); setText(historyTextArea1, winToUnicode(state.history1)); setText(historyTextArea2, winToUnicode(state.history2)); setText(memoryTextArea1, winToUnicode(state.memory1)); setText(taSensorValues, winToUnicode(state.sensorValuesText)); setText(taDeviceValues, winToUnicode(state.deviceValuesText)); enableBodyControls(!state.body.get().used); if (!smartyBrainPersistence) resetSmarty(); if (!isDevVersion()) showHelp(); else { // goCmd(); // selfTest(); } } // end of main function static boolean isDevVersion() { return isProgramID("#1031104"); } static void updateTabs() { scpVisionConfig.setComponent(visionConfigPanel(state.body.get())); scpWheelsConfig.setComponent(wheelsConfigPanel(state.body.get())); scpCurrentSmarty.setComponent(disableTextField(jLiveValueTextField(conceptFieldLiveValue("name", state.body.get())))); updateFrameTitles(); } static void enableBodyControls(boolean b) { var panels = ll(scpVisionConfig, scpWheelsConfig); for (var c : concatMap(panel -> allChildrenOfType(JComponent.class, panel), panels)) if (isInstanceOfAny(c, JCheckBox.class, JRadioButton.class, JTextField.class) && !(c instanceof BodyNameField)) setEnabled(c, b); // Modify body button is enabled iff controls are not enabled for (var c : concatMap(panel -> allChildrenOfType(ModifyBodyButton.class, panel), panels)) setEnabled(c, !b); } static void showHelp() { String text = loadSnippet(helpTextID); String heading = firstLine(text); trim(dropFirstLine(text)); showCenterFrame(swingScale(650), swingScale(500), heading, makeUneditableWithTextColor(Color.black, wordWrapTextArea(text))); } // run in Swing thread static void showHistory() { Font ttFont = loadFont_cached(monospacedFontID, 12), helpFont = sansSerifFont(13); if (historyFrame == null) historyFrame = getFrame(showCenterFrame(maxPt(pt(800, 600), scalePt(600, 350, swingFontScale())), "History", withMargin(centerAndSouthWithMargin(spacing, centerAndSouthWithMargin(historyTextArea1, westAndCenterWithMargin(spacing, setFont(ttFont, topAlignLabel(jMultiLineLabel(linesLL("Step #", "Percept", "Binon #", "", "Expect", "Binon #", "", "Action", "Binon #", "", "Action", "Binon #", "")))), setFont(ttFont, historyTextArea2))), centerAndEastWithMargin(setFont(helpFont, jMultiLineLabel(historyHelp)), jvstackWithSpacing(jButton("See World", new Runnable() { public void run() { try { showWorld(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showWorld();"; } }), jButton("See Memory", new Runnable() { public void run() { try { showMemory(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showMemory();"; } }))))))); else frameToFront(historyFrame); updateFrameTitles(); } // run in Swing thread static void showMemory() { Font ttFont = typeWriterFont(12), helpFont = sansSerifFont(13); String Interestng; if (smarty.InterestLevels == 3) Interestng = smarty.IntSymb(smarty.INTERESTING) + "=Interesting, "; else // Only 2 interest levels Interestng = ""; String IntSymbol = " " + smarty.IntSymb(smarty.NOVEL) + " = Novel, " + Interestng + smarty.IntSymb(smarty.FAMILIAR) + " = Familiar"; // originally: BinonDisplay.ObjListTitle.Caption String title = "Bn# OL Ty TL BL TR BR V L R In LQ RQ Pattern " + " l = Left target, r = Right target," + IntSymbol; if (memoryFrame == null) memoryFrame = getFrame(showCenterFrame(scalePt(600, 350, swingFontScale()), "Smarty's Memory", jvsplit(0.5, 100, centerAndEastWithMargins(northAndCenterWithMargin(setFont(ttFont, jLabel(title)), setFont(ttFont, memoryTextArea1)), jvstackWithSpacing(jButton("See World", new Runnable() { public void run() { try { showWorld(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showWorld();"; } }), jButton("See History", new Runnable() { public void run() { try { showHistory(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showHistory();"; } }))), memoryTextArea2))); else frameToFront(memoryFrame); updateFrameTitles(); } static void showWorld() { frameToFront(mainFrame); } static JRadioButton visionModeRadioButton(SmartyBody body, ButtonGroup buttonGroup, String visionMode, String text) { var rb = jradiobutton(buttonGroup, text, eq(body.visionMode, visionMode)); onChange(rb, new Runnable() { public void run() { try { if (isChecked(rb)) { cset(body, "visionMode", visionMode); body.userCausedChange(); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (isChecked(rb)) { cset(body, +visionMode); body.userCausedChange(); }"; } }); return rb; } static class ModifyBodyButton extends JButton { ModifyBodyButton() { super("Modify Smarty's Body"); main.addActionListener(this, new Runnable() { public void run() { try { modifyBody(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "modifyBody();"; } }); } } // enable the controls to edit the body, after confirmation static void modifyBody() { if (state.body.get().used) { if (!confirmOKCancel("Modifying Smarty's body will reset its state. Do you wish to continue?")) return; resetSmarty(); cset(state.body, "used", false); } enableBodyControls(true); } static class BodyNameField extends JTextField { BodyNameField() { setEnabled(false); } } static JComponent bodyNamePanel(SmartyBody body) { SimpleLiveValue lv = conceptFieldLiveValue("name", body); lv.onChange(new Runnable() { public void run() { try { body.userCausedChange(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "body.userCausedChange()"; } }); return hstackWithSpacing(jMinWidth(swingScale(250), withLabel("Body name:", bindTextComponentToLiveValue(lv, swing(() -> new BodyNameField())))), swing(() -> new ModifyBodyButton())); } static JComponent visionConfigPanel(SmartyBody body) { var buttonGroup = buttonGroup(); return northAndCenterWithMargins(spacing, bodyNamePanel(body), westAndCenterWithMargin(spacing, jCenteredSection("Camera", withLeftMargin(spacing, jvstackWithSpacing(spacing, itemPlus(jlabel("Select the camera directions"), map(CameraDirection.all, direction -> { var cb = jCheckBox(direction, body.cameraDirections.contains(direction)); onChange(cb, new Runnable() { public void run() { try { addOrRemove(body.cameraDirections, direction, isChecked(cb)); body.userCausedChange(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addOrRemove(body.cameraDirections, direction, isChecked(cb)); body.userCaused..."; } }); return cb; }))))), jCenteredSection("Vision mode", jvstack(withLeftMargin(spacing * 2, jMultiLineLabel(unindentMLS(replaceSymbols("\r\n Square locations are identified with a letter.\r\n Looking down provides the letter of the current square.\r\n Looking in other directions provides the letter in the next square\r\n depending on the direction Smarty is facing.\r\n If it is a wall then the symbolic stimulus is a $wallSymbol\r\n ")))), visionModeRadioButton(body, buttonGroup, VisionMode.nextSquare, "Looking at the next square (symbolic values = letter in square)"), verticalStrut(20), withLeftMargin(spacing * 2, jMultiLineLabel(unindentMLS("\r\n Looking at the distance to the nearest wall will provide the\r\n number of squares from the current position to the wall in\r\n the direction the camera is facing. A wall next to the robot\r\n is one square away. Looking down will always return 1.\r\n "))), visionModeRadioButton(body, buttonGroup, VisionMode.distanceToWall, "Distance to wall (magnitude values = number of squares)"), verticalStrut(20), withLeftMargin(spacing * 2, jMultiLineLabel(unindentMLS("\r\n Looking at the next square will either see a wall or an empty square\r\n "))), visionModeRadioButton(body, buttonGroup, VisionMode.wallOrNot, replaceSymbols("Wall or not (symbolic values = $wallSymbol for a wall and $noWallSymbol for no wall)")))))); } static void showVisionConfig(SmartyBody body) { showPackedFrame("Configure Smarty's Vision", visionConfigPanel(body)); } static JCheckBox wheelsConfigCheckBox(SmartyBody body, String symbol, String text) { var cb = jCheckBox(text, body.wheels.contains(symbol)); onChange(cb, new Runnable() { public void run() { try { addOrRemove(body.wheels, symbol, isChecked(cb)); body.userCausedChange(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addOrRemove(body.wheels, symbol, isChecked(cb)); body.userCausedChange();"; } }); return cb; } static JComponent wheelsConfigPanel(SmartyBody body) { return northAndCenterWithMargins(spacing, bodyNamePanel(body), vstackWithSpacing(spacing, westAndCenterWithMargin(spacing, jCenteredSection("Movement", withLeftMargin(spacing, jvstackWithSpacing(jlabel("Select the wheel motions"), wheelsConfigCheckBox(body, "MoveForward", "Forward = f"), wheelsConfigCheckBox(body, "MoveLeft", "Left = l"), wheelsConfigCheckBox(body, "MoveRight", "Right = r"), wheelsConfigCheckBox(body, "MoveBackward", "Backward = b")))), jCenteredSection("Help", withLeftMargin(jTopLabel(hhtml(nlToBr(mls_replaceDollarVars(winToUnicode("\r\n Motion in any direction will move one square.\r\n If there is a wall in the way it will not move. A \"-\" indicates no motion.\r\n The direction moved depends on the direction Smarty is facing.\r\n Smarty will appear as a $smiley if it cannot turn. It will then always be\r\n facing North (up) so moving right will move to the East (right).\r\n "), "smiley", himgForJLabel("#1102987", "width", swingScale(15), "height", swingScale(15), "align", "middle")))))))), westAndCenterWithMargin(spacing, jCenteredSection("Turning", withLeftMargin(spacing, vstackWithSpacing(wheelsConfigCheckBox(body, "TurnRight", "Turn to the right = Rotate clockwise 90 degrees = " + winToUnicode(Smarty.TurnRght)), wheelsConfigCheckBox(body, "TurnLeft", "Turn to the left = Rotate anti-clockwise 90 degrees = " + winToUnicode(Smarty.TurnLft)), wheelsConfigCheckBox(body, "TurnAround", "Turn around = Rotate 180 degrees = " + winToUnicode(Smarty.TurnArnd))))), jCenteredSection("Help", withLeftMargin(jMultiLineLabel(winToUnicode(mls_replaceDollarVars("\r\n Turning will stay on the same square. If Smarty is able to turn then it will appear as $left, $right, $up or $down to indicate the direction it is facing.\r\n ", "left", Smarty.LeftArrow, "right", Smarty.RightArrow, "up", Smarty.UpArrow, "down", Smarty.DownArrow)))))), jCenteredSection("Sensing", withLeftMargin(spacing, wheelsConfigCheckBox(body, "AddAWheelSensor", "Add a wheel sensor to detect if it moved or failed because it was up against a wall"))))); } static void showWheelsConfig(SmartyBody body) { var buttonGroup = buttonGroup(); showPackedFrame("Configure Smarty's Wheels", wheelsConfigPanel(body)); } static void showSmartyConfig() { showPackedFrameMinWidth(400, "Design or Select a body for Smarty", withMargin(centeredButtons("Vision", new Runnable() { public void run() { try { showVisionConfig(state.body.get()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showVisionConfig(state.body.get())"; } }, "Wheels", new Runnable() { public void run() { try { showWheelsConfig(state.body.get()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "showWheelsConfig(state.body.get())"; } }))); } // e.g. $wallSymbol and $noWallSymbol static String replaceSymbols(String s) { return replaceDollarVars(s, "wallSymbol", wallSymbol, "noWallSymbol", noWallSymbol); } static String exportWorldForSaving() { List lines = new ArrayList(); lines.add(" " + state.gridRows); for (int y = 0; y < state.gridRows; y++) for (int x = 0; x < state.gridCols; x++) { JCell cell = getCell(x, y); lines.add(state.smartyX == x && state.smartyY == y ? "A" : cell.obstacle() ? "#" : " "); } return lines(lines); } static void saveWorld(File f) { String text = exportWorldForSaving(); saveTextFile(f, text); infoBox("World saved: " + fileName(f)); cset(state, "worldName", fileNameWithoutExtension(f), "worldChanged", false); addRecentWorldFile(f); } static void addRecentWorldFile(File f) { swing(new Runnable() { public void run() { try { removeAndPut(state.recentWorldFiles, f, true); state.change(); makeMenus(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "removeAndPut(state.recentWorldFiles, f, true);\r\n state.change();\r\n makeMenu..."; } }); } static void addRecentBodyFile(File f) { swing(new Runnable() { public void run() { try { removeAndPut(state.recentBodyFiles, f, true); state.change(); makeMenus(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "removeAndPut(state.recentBodyFiles, f, true);\r\n state.change();\r\n makeMenus();"; } }); } static void loadWorld(File f) { try { List lines = linesFromFile_list(f); if (eqAfterRtrim(lines(lines), exportWorldForSaving())) { infoBox("World is the same as current one"); return; } int i = 0; int gridRows = parseInt(trim(lines.get(i++))); if (gridRows < 1 || gridRows > maxWorldSize) throw fail("Bad world size: " + gridRows); setWorldSize(gridRows); for (int y = 0; y < gridRows; y++) for (int x = 0; x < gridRows; x++) { String line = lines.get(i++); JCell cell = getCell(x, y); if (eq(line, "#")) cell.setObstacle(true); else if (eq(line, "A")) state.moveSmarty(x, y); } rearrangeLetters(); repaintGrid(); cset(state, "worldName", fileNameWithoutExtension(f)); cset(state, "worldChanged", false); infoBox("World loaded: " + fileName(f)); addRecentWorldFile(f); } catch (Throwable __e) { messageBox(__e); } } static void saveWorldDialog() { saveWorldDialog(null); } static void saveWorldDialog(Runnable whenDone) { { swing(new Runnable() { public void run() { try { JFileChooser fileChooser = new JFileChooser(mainDir()); fileChooser.setFileFilter(new FileNameExtensionFilter(("Smarty World files (*." + worldFileExtension + ")"), worldFileExtension)); if (fileChooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) { File f = defaultExtension(worldFileExtension, fileChooser.getSelectedFile()); saveWorld(f); infoBox("World saved as " + f.getName()); } else messageBox("World NOT saved"); callF(whenDone); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JFileChooser fileChooser = new(mainDir());\r\n fileChooser.setFileFilter(new..."; } }); } } static void withWorldSave(Runnable r) { if (state.worldChanged) { int result = swingShowConfirmDialog(mainFrame, "World has changed! - Save it?", "Smarty", JOptionPane.YES_NO_CANCEL_OPTION); if (result == JOptionPane.YES_OPTION) { saveWorldDialog(r); return; } else if (result == JOptionPane.CANCEL_OPTION) return; else cset(state, "worldChanged", false); } r.run(); } static void loadWorldDialog() { withWorldSave(new Runnable() { public void run() { try { loadWorldDialogWithoutConfirmation(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadWorldDialogWithoutConfirmation();"; } }); } static void loadWorldDialogWithoutConfirmation() { swing(new Runnable() { public void run() { try { JFileChooser fileChooser = new JFileChooser(mainDir()); fileChooser.setFileFilter(new FileNameExtensionFilter(("Smarty World files (*." + worldFileExtension + ")"), worldFileExtension)); if (fileChooser.showOpenDialog(mainFrame) == JFileChooser.APPROVE_OPTION) loadWorld(fileChooser.getSelectedFile()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JFileChooser fileChooser = new(mainDir());\r\n fileChooser.setFileFilter(new F..."; } }); } static void newWorld() { withWorldSave(new Runnable() { public void run() { try { newWorldWithoutConfirmation(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newWorldWithoutConfirmation();"; } }); } static void newWorldWithoutConfirmation() { newWorldWithoutConfirmation(defaultWorldSize); } static void newWorldWithoutConfirmation(int size) { setWorldSize(size); cset(state, "worldName", "Empty", "worldChanged", false); updateFrameTitles(); } static File mainDir() { return mkdirs(userDir("Adaptron/Smarty")); } static String exportBodyForSaving() { String[] Body = new String[22]; bodyToArray(state.body.get(), Body); return lines(dropFirst(Body)); } static void saveBody(File f) { String text = exportBodyForSaving(); saveTextFile(f, text); cset(state.body.get(), "changed", false); addRecentBodyFile(f); } static void bodyToArray(SmartyBody b, String[] Body) { Body[1] = escapeNewLines(b.name); // TODO: remaining values from AI? // Vision.Value = 1 - checked Body[2] = "1"; // Touch.Value Body[3] = "0"; Body[4] = b.wheelsFlag("AddAWheelSensor"); // Wheels.Value Body[5] = "1"; // Arms.Value Body[6] = "0"; // VisionConfig.VisionDown Body[7] = b.cameraDirections.contains(CameraDirection.down) ? "1" : "0"; // VisionConfig.VisionLeft Body[8] = b.cameraDirections.contains(CameraDirection.left) ? "1" : "0"; // VisionConfig.VisionRight Body[9] = b.cameraDirections.contains(CameraDirection.right) ? "1" : "0"; // VisionConfig.VisionInFront Body[10] = b.cameraDirections.contains(CameraDirection.inFront) ? "1" : "0"; // VisionConfig.VisionBehind Body[11] = b.cameraDirections.contains(CameraDirection.behind) ? "1" : "0"; // VisionConfig.VisionSymbolicOrMagnitude(0) Body[12] = eq(b.visionMode, VisionMode.nextSquare) ? "True" : "False"; // VisionConfig.VisionSymbolicOrMagnitude(1) Body[13] = eq(b.visionMode, VisionMode.distanceToWall) ? "True" : "False"; Body[14] = b.wheelsFlag("MoveForward"); Body[15] = b.wheelsFlag("MoveLeft"); Body[16] = b.wheelsFlag("MoveRight"); Body[17] = b.wheelsFlag("MoveBackward"); Body[18] = b.wheelsFlag("TurnRight"); Body[19] = b.wheelsFlag("TurnLeft"); Body[20] = b.wheelsFlag("TurnAround"); // VisionConfig.VisionSymbolicOrMagnitude(2) Body[21] = eq(b.visionMode, VisionMode.wallOrNot) ? "True" : "False"; } static void withBodySave(Runnable r) { if (state.body.get().changed) { int result = swingShowConfirmDialog(mainFrame, "Body has changed! - Save it?", "Smarty", JOptionPane.YES_NO_CANCEL_OPTION); if (result == JOptionPane.YES_OPTION) { saveBodyDialog(r); return; } else if (result == JOptionPane.CANCEL_OPTION) return; else cset(state.body, "changed", false); } r.run(); } static void newBody() { withBodySave(new Runnable() { public void run() { try { newBodyWithoutConfirmation(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newBodyWithoutConfirmation();"; } }); } static void newBodyWithoutConfirmation() { cdelete(state.body.get()); cset(state, "body", cnew(SmartyBody.class)); finishBodySetup(); } static void loadBody(File f) { try { List lines = linesFromFile_list(f); if (eqAfterRtrim(lines(lines), exportBodyForSaving())) { infoBox("Body is the same as current one"); return; } String[] Body = asStringArray(itemPlusList("", lines)); newBody(); var b = state.body.get(); // TODO: remaining values cset(b, "name", Body[1]); if (eq(Body[4], "1")) b.wheels.add("AddAWheelSensor"); if (eq(Body[7], "1")) b.cameraDirections.add(CameraDirection.down); if (eq(Body[8], "1")) b.cameraDirections.add(CameraDirection.left); if (eq(Body[9], "1")) b.cameraDirections.add(CameraDirection.right); if (eq(Body[10], "1")) b.cameraDirections.add(CameraDirection.inFront); if (eq(Body[11], "1")) b.cameraDirections.add(CameraDirection.behind); if (eq(Body[12], "True")) b.visionMode = VisionMode.nextSquare; if (eq(Body[13], "True")) b.visionMode = VisionMode.distanceToWall; if (eq(Body[14], "1")) b.wheels.add("MoveForward"); if (eq(Body[15], "1")) b.wheels.add("MoveLeft"); if (eq(Body[16], "1")) b.wheels.add("MoveRight"); if (eq(Body[17], "1")) b.wheels.add("MoveBackward"); if (eq(Body[18], "1")) b.wheels.add("TurnRight"); if (eq(Body[19], "1")) b.wheels.add("TurnLeft"); if (eq(Body[20], "1")) b.wheels.add("TurnAround"); if (eq(Body[21], "True")) b.visionMode = VisionMode.wallOrNot; cset(b, "changed", false); b.change(); updateTabs(); infoBox("Body loaded: " + fileName(f)); addRecentBodyFile(f); finishBodySetup(); } catch (Throwable __e) { messageBox(__e); } } static void saveBodyDialog() { saveBodyDialog(null); } static void saveBodyDialog(Runnable whenDone) { { swing(new Runnable() { public void run() { try { JFileChooser fileChooser = new JFileChooser(); fileChooser.setSelectedFile(newFile(mainDir(), sanitizeFileName(state.body.get().name))); fileChooser.setFileFilter(new FileNameExtensionFilter(("Smarty Body files (*." + bodyFileExtension + ")"), bodyFileExtension)); if (fileChooser.showSaveDialog(mainFrame) == JFileChooser.APPROVE_OPTION) { File f = defaultExtension(bodyFileExtension, fileChooser.getSelectedFile()); cset(state.body, "name", fileNameWithoutExtension(f)); updateTabs(); saveBody(f); infoBox("Body saved as " + f.getName()); } callF(whenDone); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new JFileChooser fileChooser;\r\n fileChooser.setSelectedFile(newFile(mainDi..."; } }); } } static void loadBodyDialog() { withBodySave(new Runnable() { public void run() { try { loadBodyDialogWithoutConfirmation(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadBodyDialogWithoutConfirmation();"; } }); } static void loadBodyDialogWithoutConfirmation() { swing(new Runnable() { public void run() { try { JFileChooser fileChooser = new JFileChooser(mainDir()); fileChooser.setFileFilter(new FileNameExtensionFilter(("Smarty Body files (*." + bodyFileExtension + ")"), bodyFileExtension)); if (fileChooser.showOpenDialog(mainFrame) == JFileChooser.APPROVE_OPTION) loadBody(fileChooser.getSelectedFile()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JFileChooser fileChooser = new(mainDir());\r\n fileChooser.setFileFilter(new F..."; } }); } static String infosForWindowTitle() { return " - World= " + state.worldName + ", Body= " + state.body.get().name + ", Run done on " + simpleDateFormat_defaultTZ_now("MM-dd-YYYY") + " (mm-dd-yyyy) " + simpleDateFormat_defaultTZ_now("HH:mm:ss"); } static void updateFrameTitles() { frameTitle(mainFrame, "Smarty's World" + infosForWindowTitle()); frameTitle(historyFrame, "Stimulus/Response, Percept/Action History" + infosForWindowTitle()); frameTitle(memoryFrame, "Smarty's Memory" + infosForWindowTitle()); } // Make the dynamic menus static void makeMenus() { addMenu(mainFrame, "Worlds", "New... (Ctrl+N)", new Runnable() { public void run() { try { newWorld(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newWorld();"; } }, "Retrieve... (Ctrl+R)", new Runnable() { public void run() { try { loadWorldDialog(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadWorldDialog();"; } }, "Save... (Ctrl+S)", new Runnable() { public void run() { try { saveWorldDialog(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "saveWorldDialog();"; } }, "---", mapWithIndexStartingAt1(reversed(keys(state.recentWorldFiles)), (idx, f) -> jMenuItem(idx + " " + fileName(f), new Runnable() { public void run() { try { withWorldSave(new Runnable() { public void run() { try { loadWorld(f); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadWorld(f)"; } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "withWorldSave(r { loadWorld(f) })"; } })), empty(state.recentWorldFiles) ? null : "---", "Exit", runnableThread(new Runnable() { public void run() { try { killVM(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "killVM();"; } })); addMenu(mainFrame, "Bodies", "New... (Ctrl+N)", new Runnable() { public void run() { try { newBody(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "newBody();"; } }, "Retrieve... (Ctrl+R)", new Runnable() { public void run() { try { loadBodyDialog(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadBodyDialog();"; } }, "Save... (Ctrl+S)", new Runnable() { public void run() { try { saveBodyDialog(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "saveBodyDialog();"; } }, "---", mapWithIndexStartingAt1(reversed(keys(state.recentBodyFiles)), (idx, f) -> jMenuItem(idx + " " + fileName(f), new Runnable() { public void run() { try { withBodySave(new Runnable() { public void run() { try { loadBody(f); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "loadBody(f)"; } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "withBodySave(r { loadBody(f) })"; } })), empty(state.recentBodyFiles) ? null : "---", "Exit", runnableThread(new Runnable() { public void run() { try { killVM(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "killVM();"; } })); } static void goCmd() { smartyQ.add(new Runnable() { public void run() { try { goCmd_impl(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "goCmd_impl();"; } }); } static void goCmd_impl() { try { evalWithTimeout(10.0, new Runnable() { public void run() { try { print("goCmd"); if (!state.body.get().used) { finishBodySetup(); cset(state.body, "used", true); enableBodyControls(false); } smarty.bodies.BodyFunction2(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "print(\"goCmd\");\r\n \r\n if (!state.body.get().used) {\r\n finishB..."; } }); } catch (Throwable __e) { messageBox(__e); } } static int Indx(int row, int col) { // C is the across / column location - 0 based // R is the down / row location - 0 based // the function gives the index into NG and CWP linear arrays - 0 based // can not be greater than 199 because 200+ used for wall letters return state.gridCols * row + col; } // NG(I).Caption is contents of cell x/y // with I = WallNo(x, y, direction) // NG Caption is either "" or smarty.Smarty // or Chr$(64 + InNG - 200) [location letter?] // WP$ seems to hold the playing field // WP$(R, C) can be ABlock$ /* From Brett: WP$ contains either a space, a block or the smarty symbol. The smarty symbol may be an S, >, <, ^, v or + depending on which way smarty is pointing. NG().captions contain the letter for each location. The LookUnder$() routine returns the letter for the camera that looks down at the current square. LookNorth$() etc. and other Look routines return the cell letter that is one cell away. The higher index values into NG() can contain letter for the walls set by the IDWalls() routine. But this feature is not in use and the higher index entries of NG are invisible so a mouse down cannot be done on them. Note also that ScopeLeft$() and other Scope routines that would return wall letters are not in use. */ static int InRow() { return state.smartyY; } static int InCol() { return state.smartyX; } static void setSmartyDirection(String smartyDirection) { if (cset_trueIfChanged(state, "smartyDirection", smartyDirection)) repaintGrid(); } // query cell for Smarty's brain static String WP(int y, int x) { if (x == InCol() && y == InRow()) return state.smartyDirection; else return getCell(x, y).obstacle() ? smarty.ABlock : smarty.ASpace; } // put more static functions here static class TheWorld extends Smarty.TheWorld { // find what letter we are standing on public String LookUnder() { return str(smartyCell().letter); } void moveRelative(int x, int y) { x += state.smartyX; y += state.smartyY; if (!inGrid(x, y) || getCell(x, y).obstacle()) smarty.Motion = smarty.NoMove; else { smarty.Motion = "Y"; state.moveSmarty(x, y); } } public void MoveWest() { moveRelative(-1, 0); } public void MoveSouth() { moveRelative(0, 1); } public void MoveEast() { moveRelative(1, 0); } public void MoveNorth() { moveRelative(0, -1); } public void DisplayStimuliAndResponse(int[][][] inputValues, char response) { List leftStack = new ArrayList(); List rightStack = new ArrayList(); for (int Sens = 1; Sens <= smarty.NumSenses; Sens++) { int NumSensors = smarty.Senses[Sens][smarty.NumberOfSensors]; if (NumSensors == 0) continue; if (NumSensors != 1) warn("More than one sensor in sense"); String label = smarty.Sense[Sens] + ":"; var inputValue = inputValues[Sens][smarty.Valu][smarty.Fired]; String text; if (smarty.Senses[Sens][smarty.SymbolicOrMagnitude] == smarty.Magnitude) text = str(charPlus(inputValue, '0')) + (debugValues ? " [magn " + inputValue + "]" : ""); else text = lookupOrKeep(winToUnicode, str((char) inputValue)) + // A, B, C etc (debugValues ? " [char " + inputValue + "]" : ""); leftStack.add(withLabel(withTypeWriterFont(jlabel(label)), jlabel(text))); } for (int Devs = 1; Devs <= smarty.NumDevices; Devs++) { String label = smarty.Device[Devs] + ":"; rightStack.add(withLabel(withTypeWriterFont(jlabel(label)), jlabel(winToUnicode(response)))); } scpStimuliAndResponse.set(jhgridWithSpacing(vstack(leftStack), vstack(rightStack))); } public void Update_View() { // called by World.LookInside_Click() to SeeHistory and Bodies.BodyFunction2() // refreshes all the subwindows historyDisplay(); dumpLTM(); } public void setBinonDisplayObjList(String text) { cset(state, "memory1", text); setText(memoryTextArea1, winToUnicode(text)); } public void setBinonDisplayChngResults(String text) { cset(state, "binonDisplayChngResults", text); rstUpdateChngResults.trigger(); } public void appendBinonDisplayChngResults(String text) { cset(state, "binonDisplayChngResults", state.binonDisplayChngResults + text); rstUpdateChngResults.trigger(); } String lookDirection(int dx, int dy) { int x = InCol() + dx, y = InRow() + dy; // If off top of board or next one is a block if (// must be on board inGrid(x, y)) if (eq(WP(y, x), smarty.ABlock)) // looking at a wall return smarty.Wall; else // valid square to move into return str(getCell(x, y).letter); else // looking beyond grid return smarty.Wall; } public String LookNorth() { return lookDirection(0, -1); } public String LookSouth() { return lookDirection(0, 1); } public String LookWest() { return lookDirection(-1, 0); } public String LookEast() { return lookDirection(1, 0); } public void PointUnder() { setSmartyDirection(smarty.Smarty); } public void PointNorth() { setSmartyDirection(smarty.UpArrow); } public void PointSouth() { setSmartyDirection(smarty.DownArrow); } public void PointWest() { setSmartyDirection(smarty.LeftArrow); } public void PointEast() { setSmartyDirection(smarty.RightArrow); } public int RangeNorth() { return rangeDirection(0, -1); } public int RangeSouth() { return rangeDirection(0, 1); } public int RangeWest() { return rangeDirection(-1, 0); } public int RangeEast() { return rangeDirection(1, 0); } public int rangeDirection(int dx, int dy) { // Distance to wall int x = InCol(), y = InRow(); int i = 0; do { ++i; x += dx; y += dy; // End if off rightside of board or next one is a block } while (inGrid(x, y) && !getCell(x, y).obstacle()); return i; } public void showSensorValues(String text) { cset(state, "sensorValuesText", text); setText(taSensorValues, winToUnicode(text)); } public void showDeviceValues(String text) { cset(state, "deviceValuesText", text); setText(taDeviceValues, winToUnicode(text)); } } // end of TheWorld static void initSmarty() { smarty.World = new TheWorld(); smarty.Initialize_Adaptron(); } static void finishBodySetup() { resetSmarty(); } static void resetSmarty() { print("Finishing body setup"); ResetSmartyLocation(); // set all memory, S-List, Habit stack smarty.Reset_Adaptron(); cset(state, "history1", "", "history2", "", "memory1", ""); setText(historyTextArea1, ""); setText(historyTextArea2, ""); setText(memoryTextArea1, ""); setText(memoryTextArea2, ""); bodyToArray(state.body.get(), smarty.BodySetting); // pnl("BodySetting", smarty.BodySetting); /*if (Vision.Value = 1)*/ smarty.SetupVision(); // if (Touch.Value = 1) smarty.SetupTouch(); /*if (Wheels.Value = 1)*/ smarty.SetupWheels(); // if (Arms.Value = 1) smarty.SetupArms(); // Setup display of stimuli at bottom of World screen SetupStimulusResponseDisplay(); updateTabs(); } // not needed static void SetupStimulusResponseDisplay() { } // from Adapt.frm / HISTORYDISPLAY static void historyDisplay() { List lines = new ArrayList(); StringBuilder[] ILines$ = new StringBuilder[10 + 1]; // After 250 events the IO.Text area wraps the lines int GroupSize = 250; StringBuilder NumberLine$ = new StringBuilder(); StringBuilder OLine1$ = new StringBuilder(); for (int Group = 0; Group <= (smarty.LIN - 1) / GroupSize; Group++) { int EndLIN = min(GroupSize * Group + GroupSize, smarty.LIN); for (int E = GroupSize * Group + 1; E <= EndLIN; E++) { if (E == GroupSize * Group + 1) { // If it is the 1st position / event in the line then NumberLine$ = new StringBuilder("Step # : "); for (// Add labels to start of lines int Sn = 1; // Add labels to start of lines Sn <= smarty.NumSenses; // Add labels to start of lines Sn++) // The name of the sense ILines$[Sn] = new StringBuilder(takeFirst(smarty.Sense[Sn] + ": ", 9)); // The name of the action device OLine1$ = new StringBuilder(takeFirst(smarty.Device[1] + ": ", 9)); } // visual-basic style int-to-string! String E_str = " " + E; // the event number NumberLine$.append(E_str); // the space taken up by the event number int Wdth = l(E_str); for (int Sn = 1; Sn <= smarty.NumSenses; Sn++) ILines$[Sn].append(takeLast(" " + smarty.INPUTS[E][Sn], Wdth)); OLine1$.append(takeLast(" " + smarty.OUTPUTS[E][1], Wdth)); } lines.add(str(NumberLine$)); for (int Sn = 1; Sn <= smarty.NumSenses; Sn++) lines.add(str(ILines$[Sn])); lines.add(str(OLine1$)); lines.add(""); } String text = rtrim(lines(lines)); cset(state, "history1", text); setText(historyTextArea1, winToUnicode(text)); } // end of historyDisplay static void dumpLTM() { // Called by Update_View String MemValT = null; int[] MemSize = new int[2000 + 1]; String Sen = null; String Att = null; String Pe = null; String Ob = null; Object BinTyp = null; // a Spac$, boolean DisplayIt = false; // '-------------------- Long Term Memory (LTM) - Monitoring Info. ------------------------- // 'For Display purposes only by Adapt.DUMPLTM in Adapt.LTMem // 'Long term memory contains a list of the stimuli that have been paid attention to. // 'It stores Perceptual sequences as a pair of sequential memory locations. // // Public LTMEMORY&(1 To 2000, 1 To 6) // '1st index is StoreAt cycle number // '2nd index is what type of information is in the LTM // // '---- LTMEMORY() 2nd index values - type of information in LTMEMORY() // Public LtmPerceptTyp '1 Percept binon type // Public LtmPerceptBin '2 Percept binon // Public LtmESType '3 Type of ES Binon - may be an SS // Public LtmESActBin '4 ES Actbin // Public LtmARType '5 Type of AR Binon - may be an RR // Public LtmARActBin '6 AR ActBin // Public LtmActionTyp '7 Action binon type // Public LtmActionBin '8 Action binon for (// find the widest binon # for all the StoreAt positions var I = 1; // find the widest binon # for all the StoreAt positions I <= smarty.StoreAt; // find the widest binon # for all the StoreAt positions I++) { MemSize[I] = intMax(l(str(I)) + 1, 3, l(vbToStr(smarty.LTMEMORY[I][smarty.LtmPerceptBin])), l(vbToStr(smarty.LTMEMORY[I][smarty.LtmESActBin])), l(vbToStr(smarty.LTMEMORY[I][smarty.LtmARActBin])), l(vbToStr(smarty.LTMEMORY[I][smarty.LtmActionBin]))); } StringBuffer text = new StringBuffer(); int GroupSize = 250; var tempVar = (smarty.StoreAt - 1) / GroupSize; for (int Group = 0; Group <= (smarty.StoreAt - 1) / GroupSize; Group++) { // Only put up the available values int EndLIN = GroupSize * Group + GroupSize; if (EndLIN > smarty.StoreAt) EndLIN = smarty.StoreAt; StringBuilder MemLine = new StringBuilder(); for (// For each event in LTM display the event number int E = GroupSize * Group + 1; // For each event in LTM display the event number E <= EndLIN; // For each event in LTM display the event number E++) MemLine.append(pad(MemSize[E], str(E))); text.append(MemLine + "\r\n"); // ------Percepts(.., Fired) Type MemLine = new StringBuilder(); for (// For each event in LTM int E = GroupSize * Group + 1; // For each event in LTM E <= EndLIN; // For each event in LTM E++) { // Att$ = Str$(STM(1, BinTp, Current)) Att = smarty.BinonTypeName[smarty.LTMEMORY[E][smarty.LtmPerceptTyp]][smarty.BinAbbreviation]; MemLine.append(pad(MemSize[E], Att)); } text.append(MemLine + "\r\n"); // ------Percepts(.., Fired) Binon // Trigger STIMULUS intensity MemLine = new StringBuilder(); for (// For each event in LTM int E = GroupSize * Group + 1; // For each event in LTM E <= EndLIN; // For each event in LTM E++) { // Att$ = Str$(STM(1, BinId, Current)) Att = str(smarty.LTMEMORY[E][smarty.LtmPerceptBin]); MemLine.append(pad(MemSize[E], Att)); } text.append(MemLine + "\r\n\r\n"); // ------ES ActBin type MemLine = new StringBuilder(); for (// For each event in LTM int E = GroupSize * Group + 1; // For each event in LTM E <= EndLIN; // For each event in LTM E++) { Att = smarty.AESR(smarty.LTMEMORY[E][smarty.LtmESActBin]); MemLine.append(pad(MemSize[E], Att)); } text.append(MemLine + "\r\n"); // ------ LTMEMORY ActBin Object binon MemLine = new StringBuilder(); for (// For each event in LTM int E = GroupSize * Group + 1; // For each event in LTM E <= EndLIN; // For each event in LTM E++) { Att = String.valueOf(smarty.LTMEMORY[E][smarty.LtmESActBin]); MemLine.append(pad(MemSize[E], Att)); } text.append(MemLine + "\r\n\r\n"); // ------AR ActBin type MemLine = new StringBuilder(); for (// For each event in LTM int E = GroupSize * Group + 1; // For each event in LTM E <= EndLIN; // For each event in LTM E++) { Att = smarty.AESR(smarty.LTMEMORY[E][smarty.LtmARActBin]); MemLine.append(pad(MemSize[E], Att)); } text.append(MemLine + "\r\n"); // ------ LTMEMORY ActBin Object binon MemLine = new StringBuilder(); for (// For each event in LTM int E = GroupSize * Group + 1; // For each event in LTM E <= EndLIN; // For each event in LTM E++) { Att = String.valueOf(smarty.LTMEMORY[E][smarty.LtmARActBin]); MemLine.append(pad(MemSize[E], Att)); } text.append(MemLine + "\r\n\r\n"); // ------Actions(.., Fired) Type MemLine = new StringBuilder(); for (// For each event in LTM int E = GroupSize * Group + 1; // For each event in LTM E <= EndLIN; // For each event in LTM E++) { Att = smarty.BinonTypeName[smarty.LTMEMORY[E][smarty.LtmActionTyp]][smarty.BinAbbreviation]; MemLine.append(pad(MemSize[E], Att)); } text.append(MemLine + "\r\n"); // ------Actions(.., Fired) Binon MemLine = new StringBuilder(); for (// For each event in LTM int E = GroupSize * Group + 1; // For each event in LTM E <= EndLIN; // For each event in LTM E++) { Att = String.valueOf(smarty.LTMEMORY[E][smarty.LtmActionBin]); MemLine.append(pad(MemSize[E], Att)); } text.append(MemLine + "\r\n\r\n"); } String s = rtrim(str(text)); cset(state, "history2", s); setText(historyTextArea2, winToUnicode(s)); } // End of dumpLTM static void uiZoom(double percent) { if (cset_trueIfChanged(state, "fontScale", toFloat(percent / 100))) restart(); } static void updateFontScale(float scale) { swingFontScale(scale); spacing = iround(defaultSpacing * scale); } static void selfTest() { new SelfTest().run(); } static class SelfTest { Scorer scorer = new Scorer(); void loadWorldAndBody(String worldText, String bodyText) { File bodyFile = programFile("body.tmp"); File worldFile = programFile("world.tmp"); saveTextFile(worldFile, dropLeadingEmptyLines(worldText)); loadWorld(worldFile); saveTextFile(bodyFile, dropLeadingEmptyLines(bodyText)); loadBody(bodyFile); } public void run() { activateConsole(); print("Self-Test START"); String text = loadSnippet("#1031220"); List parts = splitAtMultipleEqualsLines(text); assertEqualsVerbose(6, l(parts)); loadWorldAndBody(parts.get(0), parts.get(1)); List outputTexts = subList(parts, 2); do { // step 1 if (!step(outputTexts)) break; text = loadSnippet("#1031228"); outputTexts = getMulti(splitAtMultipleEqualsLines(text), 2, 3, 0, 1); // step 2 if (!step(outputTexts)) break; // step 10 text = loadSnippet("#1031229"); outputTexts = getMulti(splitAtMultipleEqualsLines(text), 0, 1, 2, 3); for (int _repeat_12 = 0; _repeat_12 < 7; _repeat_12++) { goCmd_impl(); } if (!step(outputTexts)) break; // step 50 text = loadSnippet("#1031230"); outputTexts = getMulti(splitAtMultipleEqualsLines(text), 2, 3, 0, 1); for (int _repeat_13 = 0; _repeat_13 < 39; _repeat_13++) { goCmd_impl(); } if (!step(outputTexts)) break; } while (false); // second test case text = loadSnippet("#1031231"); parts = splitAtMultipleEqualsLines(text); assertEqualsVerbose(6, l(parts)); loadWorldAndBody(parts.get(0), parts.get(1)); do { // step 30 outputTexts = getMulti(subList(parts, 2), 2, 3, 0, 1); for (int _repeat_14 = 0; _repeat_14 < 29; _repeat_14++) { goCmd_impl(); } if (!step(outputTexts)) break; } while (false); // third test case text = loadSnippet("#1031238"); parts = splitAtMultipleEqualsLines(text); assertEqualsVerbose(6, l(parts)); loadWorldAndBody(parts.get(0), parts.get(1)); do { // step 50 outputTexts = getMulti(subList(parts, 2), 2, 3, 0, 1); for (int _repeat_15 = 0; _repeat_15 < 49; _repeat_15++) { goCmd_impl(); } if (!step(outputTexts)) break; } while (false); print("SELF-TEST RESULT: " + scorer); } // returns false if something failed boolean step(List outputTexts) { goCmd_impl(); List diffs = new ArrayList(); printAsciiHeading("HISTORY 1"); print(addAndReturn(diffs, unidiff2(historyTextArea1, outputTexts.get(2)))); printAsciiHeading("HISTORY 2"); print(addAndReturn(diffs, unidiff2(historyTextArea2, outputTexts.get(3)))); printAsciiHeading("MEMORY 1"); print(addAndReturn(diffs, unidiff2(memoryTextArea1, outputTexts.get(0)))); printAsciiHeading("MEMORY 2"); print(addAndReturn(diffs, unidiff2(state.binonDisplayChngResults, outputTexts.get(1)))); boolean ok = allStringsEmpty(diffs); scorer.add(ok, nOutputs(nempties(diffs)) + " differ"); return ok; } } static String unidiff2(JTextComponent ta, String text) { return unidiff2(getText(ta), text); } static String unidiff2(String actual, String text) { return unidiff(cleanUpForDiff(text), cleanUpForDiff(actual)); } static String cleanUpForDiff(String text) { return fixNewLines(rtrim(dropLeadingEmptyLines(text))); } static void ResetSmartyLocation() { if (!getCell(state.startX, state.startY).obstacle()) state.moveSmarty(state.startX, state.startY); } static String winToUnicode(Object text) { return mapCharacters(str(text), c -> lookupOrKeep(winToUnicode, str(c))); } static A monospaced(A a) { return setFont(monospacedFontID, swingScale(monospacedFontSize), a); } static int strL(String s) { return s == null ? 0 : s.length(); } static int lCharSequence(CharSequence s) { return s == null ? 0 : s.length(); } static String str(Object o) { return o == null ? "null" : o.toString(); } static String str(char[] c) { return new String(c); } static Object first(Object list) { return first((Iterable) list); } static A first(List list) { return empty(list) ? null : list.get(0); } static A first(A[] bla) { return bla == null || bla.length == 0 ? null : bla[0]; } static A first(IterableIterator i) { return first((Iterator) i); } static A first(Iterator i) { return i == null || !i.hasNext() ? null : i.next(); } static A first(Iterable i) { if (i == null) return null; Iterator it = i.iterator(); return it.hasNext() ? it.next() : null; } static Character first(String s) { return empty(s) ? null : s.charAt(0); } static Character first(CharSequence s) { return empty(s) ? null : s.charAt(0); } static A first(Pair p) { return p == null ? null : p.a; } static Byte first(byte[] l) { return empty(l) ? null : l[0]; } static int min(int a, int b) { return Math.min(a, b); } static long min(long a, long b) { return Math.min(a, b); } static float min(float a, float b) { return Math.min(a, b); } static float min(float a, float b, float c) { return min(min(a, b), c); } static double min(double a, double b) { return Math.min(a, b); } static double min(double[] c) { double x = Double.MAX_VALUE; for (double d : c) x = Math.min(x, d); return x; } static float min(float[] c) { float x = Float.MAX_VALUE; for (float d : c) x = Math.min(x, d); return x; } static byte min(byte[] c) { byte x = 127; for (byte d : c) if (d < x) x = d; return x; } static short min(short[] c) { short x = 0x7FFF; for (short d : c) if (d < x) x = d; return x; } static int min(int[] c) { int x = Integer.MAX_VALUE; for (int d : c) if (d < x) x = d; return x; } static int l(Object[] a) { return a == null ? 0 : a.length; } static int l(boolean[] a) { return a == null ? 0 : a.length; } static int l(byte[] a) { return a == null ? 0 : a.length; } static int l(short[] a) { return a == null ? 0 : a.length; } static int l(long[] a) { return a == null ? 0 : a.length; } static int l(int[] a) { return a == null ? 0 : a.length; } static int l(float[] a) { return a == null ? 0 : a.length; } static int l(double[] a) { return a == null ? 0 : a.length; } static int l(char[] a) { return a == null ? 0 : a.length; } static int l(Collection c) { return c == null ? 0 : c.size(); } // consumes the iterator && closes it if possible static int l(Iterator i) { return iteratorCount_int_close(i); } static int l(Map m) { return m == null ? 0 : m.size(); } static int l(CharSequence s) { return s == null ? 0 : s.length(); } static long l(File f) { return f == null ? 0 : f.length(); } static int l(Object o) { return o == null ? 0 : o instanceof String ? l((String) o) : o instanceof Map ? l((Map) o) : o instanceof Collection ? l((Collection) o) : o instanceof Object[] ? l((Object[]) o) : o instanceof boolean[] ? l((boolean[]) o) : o instanceof byte[] ? l((byte[]) o) : o instanceof char[] ? l((char[]) o) : o instanceof short[] ? l((short[]) o) : o instanceof int[] ? l((int[]) o) : o instanceof float[] ? l((float[]) o) : o instanceof double[] ? l((double[]) o) : o instanceof long[] ? l((long[]) o) : (Integer) call(o, "size"); } static int l(MultiSet ms) { return ms == null ? 0 : ms.size(); } static boolean eq(Object a, Object b) { return a == b || a != null && b != null && a.equals(b); } static String rep(int n, char c) { return repeat(c, n); } static String rep(char c, int n) { return repeat(c, n); } static List rep(A a, int n) { return repeat(a, n); } static List rep(int n, A a) { return repeat(n, a); } static void change() { // mainConcepts.allChanged(); // safe version for now cause function is sometimes included unnecessarily (e.g. by EGDiff) callOpt(getOptMC("mainConcepts"), "allChanged"); } // sbool ping_actions_shareable = true; static volatile boolean ping_pauseAll = false; // poll pauseAll flag every 100 static int ping_sleep = 100; static volatile boolean ping_anyActions = false; static Map ping_actions = newWeakHashMap(); static ThreadLocal ping_isCleanUpThread = new ThreadLocal(); // always returns true static boolean ping() { if (ping_pauseAll || ping_anyActions) ping_impl(true); // ifndef LeanMode ping_impl(); endifndef return true; } // returns true when it slept static boolean ping_impl(boolean okInCleanUp) { try { if (ping_pauseAll && !isAWTThread()) { do Thread.sleep(ping_sleep); while (ping_pauseAll); return true; } if (ping_anyActions) { // don't allow sharing ping_actions if (!okInCleanUp && !isTrue(ping_isCleanUpThread.get())) failIfUnlicensed(); Object action = null; synchronized (ping_actions) { if (!ping_actions.isEmpty()) { action = ping_actions.get(currentThread()); if (action instanceof Runnable) ping_actions.remove(currentThread()); if (ping_actions.isEmpty()) ping_anyActions = false; } } if (action instanceof Runnable) ((Runnable) action).run(); else if (eq(action, "cancelled")) throw fail("Thread cancelled."); } return false; } catch (Exception __e) { throw rethrow(__e); } } static String vbToStr(long l) { return l < 0 ? str(l) : " " + l; } // Use like this: printVars_str(+x, +y); // Or: printVars("bla", +x); // Or: printVars bla(+x); static void printVars_str(Object... params) { String s = ""; if (odd(l(params))) { s = str(first(params)); if (endsWithLetterOrDigit(s)) s += ": "; params = dropFirst(params); } print(s + renderVars_str(params)); } static List replace(List l, A a, A b) { for (int i = 0; i < l(l); i++) if (eq(l.get(i), a)) l.set(i, b); return l; } static List replace(A a, A b, List l) { return replace(l, a, b); } // replace all occurrences of a in s with b static String replace(String s, String a, String b) { return s == null ? null : a == null || b == null ? s : s.replace(a, b); } static String replace(String s, char a, char b) { return s == null ? null : s.replace(a, b); } static List takeFirst(List l, int n) { return l(l) <= n ? l : newSubListOrSame(l, 0, n); } static List takeFirst(int n, List l) { return takeFirst(l, n); } static String takeFirst(int n, String s) { return substring(s, 0, n); } static String takeFirst(String s, int n) { return substring(s, 0, n); } static CharSequence takeFirst(int n, CharSequence s) { return subCharSequence(s, 0, n); } static List takeFirst(int n, Iterable i) { if (i == null) return null; List l = new ArrayList(); Iterator it = i.iterator(); for (int _repeat_0 = 0; _repeat_0 < n; _repeat_0++) { if (it.hasNext()) l.add(it.next()); else break; } return l; } static int[] takeFirst(int n, int[] a) { return takeFirstOfIntArray(n, a); } static boolean isTrue(Object o) { if (o instanceof Boolean) return ((Boolean) o).booleanValue(); if (o == null) return false; if (// TODO: remove this o instanceof ThreadLocal) return isTrue(((ThreadLocal) o).get()); throw fail(getClassName(o)); } static boolean isTrue(Boolean b) { return b != null && b.booleanValue(); } static boolean empty(Collection c) { return c == null || c.isEmpty(); } static boolean empty(Iterable c) { return c == null || !c.iterator().hasNext(); } static boolean empty(CharSequence s) { return s == null || s.length() == 0; } static boolean empty(Map map) { return map == null || map.isEmpty(); } static boolean empty(Object[] o) { return o == null || o.length == 0; } static boolean empty(Object o) { if (o instanceof Collection) return empty((Collection) o); if (o instanceof String) return empty((String) o); if (o instanceof Map) return empty((Map) o); if (o instanceof Object[]) return empty((Object[]) o); if (o instanceof byte[]) return empty((byte[]) o); if (o == null) return true; throw fail("unknown type for 'empty': " + getType(o)); } static boolean empty(Iterator i) { return i == null || !i.hasNext(); } static boolean empty(double[] a) { return a == null || a.length == 0; } static boolean empty(float[] a) { return a == null || a.length == 0; } static boolean empty(int[] a) { return a == null || a.length == 0; } static boolean empty(long[] a) { return a == null || a.length == 0; } static boolean empty(byte[] a) { return a == null || a.length == 0; } static boolean empty(short[] a) { return a == null || a.length == 0; } static boolean empty(MultiSet ms) { return ms == null || ms.isEmpty(); } static boolean empty(File f) { return getFileSize(f) == 0; } static String mapCharacters(String s, IF1 f) { return join(map(characters(s), f)); } static String mapCharacters(IF1 f, String s) { return mapCharacters(s, f); } static RuntimeException fail() { throw new RuntimeException("fail"); } static RuntimeException fail(Throwable e) { throw asRuntimeException(e); } static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); } static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); } static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); } static List takeLast(List l, int n) { return newSubList(l, l(l) - n); } static List takeLast(int n, List l) { return takeLast(l, n); } static String takeLast(int n, String s) { return substring(s, l(s) - n); } static String takeLast(String s, int n) { return substring(s, l(s) - n); } static Q startQ() { return new Q(); } static Q startQ(String name) { return new Q(name); } static String unicode_blackSquare() { return "\u25A0"; } static String unicode_dottedSquare() { return "\u2B1A"; } static java.awt.Color colorFromHex(String hex) { return awtColor(hex); } static String charRange(char first, char last) { StringBuilder buf = new StringBuilder(); while (first <= last) buf.append(first++); return str(buf); } static String charRange(int first, int last) { return charRange((char) first, (char) last); } static String unicode_slightlySmilingFace() { return codePointToString(0x1F642); } static String unindent_mls(String s) { return autoUnindent_mls(s); } static HashMap litmap(Object... x) { HashMap map = new HashMap(); litmap_impl(map, x); return map; } static void litmap_impl(Map map, Object... x) { if (x != null) for (int i = 0; i < x.length - 1; i += 2) if (x[i + 1] != null) map.put(x[i], x[i + 1]); } static String unicode(String hex) { return codePointToString(parseHexInt(hex)); } static String unicode_blackVerticalRectangle() { return unicode("25AE"); } static String unicode_whiteVerticalRectangle() { return unicode("25AF"); } static String unicode_blackSmallSquare() { return "\u25AA"; } static ReliableSingleThread rstWithPreDelay(int delay, Runnable r) { return rstWithDelay(delay, r); } static ReliableSingleThread rstWithPreDelay(double seconds, Runnable r) { return rstWithDelay(seconds, r); } // optimize by calling getText first static boolean setText_opt = true; static A setText(A c, Object text) { setText((JComponent) c, text); return c; } static A setText(final A c, Object text) { // only for editable combo boxes at this point final String s = strUnnull(text); { swing(new Runnable() { public void run() { try { c.getEditor().setItem(s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.getEditor().setItem(s);"; } }); } return c; } static void setText(JLabel c, Object text) { setText((JComponent) c, text); } static JButton setText(JButton c, Object text) { setText((JComponent) c, jlabel_textAsHTML_center_ifNeeded(strUnnull(text))); return c; } static A setText(final A c, Object text) { if (c == null) return null; final String s = strUnnull(text); { swing(new Runnable() { public void run() { try { if (!setText_opt || neq(callOpt(c, "getText"), s)) call(c, "setText", s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!setText_opt || neq(callOpt(c, \"getText\"), s))\r\n call(c, \"setText\", s);"; } }); } return c; } static RuntimeException rethrow(Throwable t) { if (t instanceof Error) _handleError((Error) t); throw t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } static RuntimeException rethrow(String msg, Throwable t) { throw new RuntimeException(msg, t); } static List ll(A... a) { ArrayList l = new ArrayList(a.length); if (a != null) for (A x : a) l.add(x); return l; } static HashSet litset(A... items) { return lithashset(items); } // not redirected static volatile StringBuffer local_log = new StringBuffer(); // might be redirected, e.g. to main bot static volatile Appendable print_log = local_log; // in bytes - will cut to half that static volatile int print_log_max = 1024 * 1024; static volatile int local_log_max = 100 * 1024; // total mute if set static boolean print_silent = false; static Object print_byThread_lock = new Object(); // special handling by thread - prefers F1 static volatile ThreadLocal print_byThread; static volatile Object print_allThreads; static volatile Object print_preprocess; static void print() { print(""); } static A print(String s, A o) { print((endsWithLetterOrDigit(s) ? s + ": " : s) + o); return o; } // slightly overblown signature to return original object... static A print(A o) { ping_okInCleanUp(); if (print_silent) return o; String s = o + "\n"; print_noNewLine(s); return o; } static void print_noNewLine(String s) { try { Object f = getThreadLocal(print_byThread_dontCreate()); if (f == null) f = print_allThreads; if (f != null) // We do need the general callF machinery here as print_byThread is sometimes shared between modules if (isFalse(f instanceof F1 ? ((F1) f).get(s) : callF(f, s))) return; } catch (Throwable e) { System.out.println(getStackTrace(e)); } print_raw(s); } static void print_raw(String s) { if (print_preprocess != null) s = (String) callF(print_preprocess, s); s = fixNewLines(s); Appendable loc = local_log; Appendable buf = print_log; int loc_max = print_log_max; if (buf != loc && buf != null) { print_append(buf, s, print_log_max); loc_max = local_log_max; } if (loc != null) print_append(loc, s, loc_max); System.out.print(s); vmBus_send("printed", mc(), s); } static void print_autoRotate() { } static Rect rect(int x, int y, int w, int h) { return new Rect(x, y, w, h); } static Rect rect(Pt p, int w, int h) { return new Rect(p.x, p.y, w, h); } static Rect rect(int w, int h) { return new Rect(0, 0, w, h); } static Pt pt(int x, int y) { return new Pt(x, y); } static Pt pt(int x) { return new Pt(x, x); } static Map synchronizedMRUCache(int maxSize) { return synchroMap(new MRUCache(maxSize)); } static boolean cset_trueIfChanged(Concept c, Object... values) { try { return cset(c, values) != 0; } catch (Exception __e) { throw rethrow(__e); } } static List pointsInRect(int w, int h) { return allPointsInRect(w, h); } static List pointsInRect(Rect r) { return allPointsInRect(r); } // better modulo that gives positive numbers always static int mod(int n, int m) { return (n % m + m) % m; } static long mod(long n, long m) { return (n % m + m) % m; } static BigInteger mod(BigInteger n, int m) { return n.mod(bigint(m)); } static double mod(double n, double m) { return (n % m + m) % m; } // returns number of changes static int cset(Concept c, Object... values) { try { if (c == null) return 0; warnIfOddCount(values = expandParams(c.getClass(), values)); int changes = 0; for (int i = 0; i + 1 < l(values); i += 2) if (_csetField(c, (String) values[i], values[i + 1])) ++changes; return changes; } catch (Exception __e) { throw rethrow(__e); } } static int cset(Iterable l, Object... values) { int changes = 0; for (Concept c : unnull(l)) changes += cset(c, values); return changes; } static int cset(Concept.Ref c, Object... values) { return cset(getVar(c), values); } static boolean inRange(int x, int n) { return x >= 0 && x < n; } static boolean inRange(int x, int a, int b) { return x >= a && x < b; } static int getWidth(Component c) { return c == null ? 0 : (int) swingCall(c, "getWidth"); } static int getHeight(Component c) { return c == null ? 0 : (int) swingCall(c, "getHeight"); } static void fillRect(BufferedImage image, int x, int y, int w, int h, Color color) { Graphics2D g = imageGraphics(image); fillRect(g, x, y, w, h, color); g.dispose(); } static void fillRect(Graphics g, int x, int y, int w, int h, Color color) { g.setColor(color); g.fillRect(x, y, w, h); } // draw on currentImage() static void fillRect(int x, int y, int w, int h, Color color) { fillRect(currentImage(), x, y, w, h, color); } static void fillRect(Rect r, Color color) { fillRect(r.x, r.y, r.w, r.h, color); } static void fillRect(BufferedImage image, Rect r, Color c) { if (r != null) fillRect(image, r.x, r.y, r.w, r.h, c); } static void fillRect(Graphics g, Rect r, Color c) { if (r != null) fillRect(g, r.x, r.y, r.w, r.h, c); } static AutoCloseable tempSetFont(Graphics g, Font font) { Font oldFont = g.getFont(); g.setFont(font); return new AutoCloseable() { public String toString() { return "g.setFont(oldFont);"; } public void close() throws Exception { g.setFont(oldFont); } }; } static Map loadFont_cached_cache = new HashMap(); static synchronized Font loadFont_cached(String snippetID) { try { snippetID = formatSnippetID(snippetID); Font f = loadFont_cached_cache.get(snippetID); if (f == null) loadFont_cached_cache.put(snippetID, f = loadFont(snippetID, 12f)); return f; } catch (Exception __e) { throw rethrow(__e); } } static synchronized Font loadFont_cached(String snippetID, float size) { try { return loadFont_cached(snippetID).deriveFont(size); } catch (Exception __e) { throw rethrow(__e); } } static void drawTextWithTopLeftCornerAt(Graphics2D g, String text, Pt p, Color color) { g.setColor(color); FontMetrics fm = g.getFontMetrics(); int h = fm.getHeight(); g.drawString(text, p.x, p.y + h); } static void _close(AutoCloseable c) { if (c != null) try { c.close(); } catch (Throwable e) { // Some classes stupidly throw an exception on double-closing if (c instanceof javax.imageio.stream.ImageOutputStream) return; else throw rethrow(e); } } static AutoCloseable tempSetFontSize(Graphics g, float size) { Font font = g.getFont(); g.setFont(font.deriveFont(size)); return new AutoCloseable() { public String toString() { return "g.setFont(font);"; } public void close() throws Exception { g.setFont(font); } }; } static int iround(double d) { return (int) Math.round(d); } static int iround(Number n) { return iround(toDouble(n)); } static void drawScaledImage(BufferedImage canvas, BufferedImage img, Rect r) { if (canvas == null || img == null || r == null) return; Graphics2D g = createGraphics(canvas); drawScaledImage(g, img, r); } static void drawScaledImage(Graphics2D g, BufferedImage img, Rect r) { if (g == null || img == null || r == null) return; double scaleX = doubleRatio(r.w, img.getWidth()); double scaleY = doubleRatio(r.h, img.getHeight()); g.translate(r.x, r.y); g.scale(scaleX, scaleY); g.drawImage(img, 0, 0, null); } static Map loadImage2_cached_cache = synchroTreeMap(); // s = snippetIDOrURL static BufferedImage loadImage2_cached(String s) { BufferedImage img = loadImage2_cached_cache.get(s); if (img == null) loadImage2_cached_cache.put(s, img = loadBufferedImage(s)); return img; } static Rect rectFromPoints(int x1, int y1, int x2, int y2) { return pointsRect(x1, y1, x2, y2); } static Rect rectFromPoints(Pt a, Pt b) { return pointsRect(a.x, a.y, b.x, b.y); } static A lookupOrKeep(Map map, A key) { return map != null && map.containsKey(key) ? map.get(key) : key; } static void drawCenteredText(Graphics2D g, String text, int x, int y, int w, int h, Color color) { g.setColor(color); FontMetrics fm = g.getFontMetrics(); Pt p = centerTextInRect(fm, text, rect(x, y, w, h)); g.drawString(text, p.x, p.y); } static boolean contains(Collection c, Object o) { return c != null && c.contains(o); } static boolean contains(Object[] x, Object o) { if (x != null) for (Object a : x) if (eq(a, o)) return true; return false; } static boolean contains(String s, char c) { return s != null && s.indexOf(c) >= 0; } static boolean contains(String s, String b) { return s != null && s.indexOf(b) >= 0; } static boolean contains(BitSet bs, int i) { return bs != null && bs.get(i); } static boolean contains(Producer p, A a) { if (p != null && a != null) while (true) { A x = p.next(); if (x == null) break; if (eq(x, a)) return true; } return false; } static boolean setBit_trueIfChanged(BitSet b, int bit) { return setBit_trueIfChanged(b, bit, true); } static boolean setBit_trueIfChanged(BitSet b, int bit, boolean value) { if (b == null || b.get(bit) == value) return false; b.set(bit, value); return true; } static void addMouseListener(final JComponent c, final MouseListener l) { if (c != null) { swing(new Runnable() { public void run() { try { c.addMouseListener(l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.addMouseListener(l);"; } }); } } static void requestFocus(final JComponent c) { focus(c); } static boolean isLeftButton(MouseEvent e) { return e.getButton() == MouseEvent.BUTTON1; } static void addMouseMotionListener(final JComponent c, final MouseMotionListener l) { if (c != null) { swing(new Runnable() { public void run() { try { c.addMouseMotionListener(l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.addMouseMotionListener(l);"; } }); } } static Component componentAtScreenLocationInWindow(Window window, int x, int y) { if (window == null) return null; return swing(new F0() { public Component get() { try { Point p = new Point(x, y); SwingUtilities.convertPointFromScreen(p, window); return SwingUtilities.getDeepestComponentAt(window, p.x, p.y); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Point p = new(x, y);\r\n SwingUtilities.convertPointFromScreen(p, window);\r\n..."; } }); } static Component componentAtScreenLocationInWindow(Window window, MouseEvent e) { Point p = e.getLocationOnScreen(); return componentAtScreenLocationInWindow(window, p.x, p.y); } static Rect rectFromPointsInclusiveSorted(int x1, int y1, int x2, int y2) { return rectFromPoints(min(x1, x2), min(y1, y2), max(x1, x2) + 1, max(y1, y2) + 1); } static List map(Iterable l, Object f) { return map(f, l); } static List map(Object f, Iterable l) { List x = emptyList(l); if (l != null) for (Object o : l) { ping(); x.add(callF(f, o)); } return x; } static List map(Iterable l, F1 f) { return map(f, l); } static List map(F1 f, Iterable l) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(callF(f, o)); } return x; } static List map(IF1 f, Iterable l) { return map(l, f); } static List map(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static List map(IF1 f, A[] l) { return map(l, f); } static List map(A[] l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : l) { ping(); x.add(f.get(o)); } return x; } static List map(Object f, Object[] l) { return map(f, asList(l)); } static List map(Object[] l, Object f) { return map(f, l); } static List map(Object f, Map map) { return map(map, f); } // map: func(key, value) -> list element static List map(Map map, Object f) { List x = new ArrayList(); if (map != null) for (Object _e : map.entrySet()) { ping(); Map.Entry e = (Map.Entry) _e; x.add(callF(f, e.getKey(), e.getValue())); } return x; } static List map(Map map, IF2 f) { return map(map, (Object) f); } static List iotaZeroList(int n) { return intRangeList(0, n); } static A setFocusable(A c) { return setFocusable(c, true); } static A setFocusable(A c, boolean b) { if (c != null) { swing(new Runnable() { public void run() { try { c.setFocusable(b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setFocusable(b);"; } }); } return c; } static A setFocusable(boolean b, A c) { return setFocusable(c, b); } static A setBackground(final Color color, final A a) { if (a != null) { swing(new Runnable() { public void run() { try { a.setBackground(color); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.setBackground(color);"; } }); } return a; } static A setBackground(A a, Color color) { return setBackground(color, a); } // TODO: all the fringe cases (?) static JPanel hvgrid(List> components) { if (empty(components)) return new JPanel(); int h = l(components), w = l(first(components)); JPanel panel = new JPanel(); panel.setLayout(new GridLayout(h, w)); for (List row : components) smartAdd(panel, row); return panel; } static JPanel hvgrid(List> components, int gap) { JPanel panel = hvgrid(components); GridLayout g = (GridLayout) (panel.getLayout()); g.setHgap(gap); g.setVgap(gap); return panel; } static void setSpinnerValue(final JSpinner s, final int value) { if (s != null) { swing(new Runnable() { public void run() { try { s.setValue(value); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "s.setValue(value);"; } }); } } static A repaint(A c) { if (c != null) c.repaint(); return c; } static String strWithIdentityHashCode(Object o) { return o == null ? "null" : "[" + identityHashCode(o) + "] " + str(o); } static Class mc() { return main.class; } static ClassLoader getClassLoader(Object o) { return o == null ? null : _getClass(o).getClassLoader(); } static double autoRestart_interval = 10; static boolean autoRestart_on, autoRestart_debug, autoRestart_simulate; static java.util.Timer autoRestart_timer; static void autoRestart(double interval) { autoRestart_interval = interval; autoRestart(); } static void autoRestart() { if (!isMain() || autoRestart_on || vmHasResourceLoader()) return; autoRestart_on = true; autoRestart_schedule(); preloadProgramTitle(); } static void autoRestart_off() { if (!autoRestart_on) return; stopTimer(autoRestart_timer); autoRestart_timer = null; } static void autoRestart_schedule() { autoRestart_timer = doLater_daemon(toMS(autoRestart_interval), "autoRestart_check"); } static void autoRestart_check() { try { String newMD5; try { newMD5 = serverAutoRestartMD5(programID()); } catch (Throwable e) { return; } if (!isMD5(newMD5)) { if (autoRestart_debug) print("autoRestart: no server transpilation"); return; } if (autoRestart_localMD5 == null) autoRestart_localMD5 = md5(loadCachedTranspilation(programID())); String localMD5 = autoRestart_localMD5(); if (neq(localMD5, newMD5)) { if (autoRestart_simulate) print("Would upgrade now. " + localMD5 + " -> " + newMD5); else { infoBox("Upgrading " + programTitle()); restartWithDelay(500); sleep(); } } } finally { if (autoRestart_debug) print("autoRestart: Done"); autoRestart_schedule(); } } static void setProgramDir(File dir) { programDir_mine = dir; } static void logProgramOutput() { logModuleOutput(); } static void hideConsole() { final JFrame frame = consoleFrame(); if (frame != null) { autoVMExit(); swingLater(new Runnable() { public void run() { try { frame.setVisible(false); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "frame.setVisible(false);"; } }); } } static void veryBigConsole() { if (headless()) return; consoleFont(loadFont("#1004970", 20f)); setConsoleHeight(500); centerBigConsole(); if (isMain()) renameConsole(programTitle()); consoleMargin(10); clearConsole(); focusConsole(); } static void db() { conceptsAndBot(); } // use -10000 for 10 seconds plus slowdown logic static void db(Integer autoSaveInterval) { conceptsAndBot(autoSaveInterval); } static A uniq(Class c, Object... params) { return uniqueConcept(c, params); } static A uniq(Concepts cc, Class c, Object... params) { return uniqueConcept(cc, c, params); } static A conceptWhere(Class c, Object... params) { return findConceptWhere(c, params); } static A conceptWhere(Concepts cc, Class c, Object... params) { return findConceptWhere(cc, c, params); } // JTattoo static void jtattoo_mcWin() { if (headless()) return; { swing(new Runnable() { public void run() { try { fixContextClassLoader(); UIManager.setLookAndFeel("com.jtattoo.plaf.mcwin.McWinLookAndFeel"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "fixContextClassLoader();\r\n UIManager.setLookAndFeel(\"com.jtattoo.plaf.mcwi..."; } }); } } static void disableSpaceBarForAllButtons() { swing(new Runnable() { public void run() { try { InputMap im = (InputMap) UIManager.get("Button.focusInputMap"); im.put(KeyStroke.getKeyStroke("pressed SPACE"), "none"); im.put(KeyStroke.getKeyStroke("released SPACE"), "none"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "InputMap im = (InputMap) UIManager.get(\"Button.focusInputMap\");\r\n im.put(Key..."; } }); } static File loadLibrary(String snippetID) { return loadBinarySnippet(snippetID); } static void defaultFrameIcon(String icon) { setDefaultFrameIcon(icon); } static JFrame showFrame() { return makeFrame(); } static JFrame showFrame(Object content) { return makeFrame(content); } static JFrame showFrame(String title) { return makeFrame(title); } static JFrame showFrame(String title, Object content) { return makeFrame(title, content); } static JFrame showFrame(final JFrame f) { if (f != null) { swing(new Runnable() { public void run() { try { if (frameTooSmall(f)) frameStandardSize(f); // XXX if (!f.isVisible()) f.setVisible(true); if (f.getState() == Frame.ICONIFIED) f.setState(Frame.NORMAL); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (frameTooSmall(f)) frameStandardSize(f);\r\n if (!f.isVisible()) f.setVis..."; } }); } return f; } // make or update frame static JFrame showFrame(String title, Object content, JFrame frame) { if (frame == null) return showFrame(title, content); else { frame.setTitle(title); setFrameContents(frame, content); return frame; } } static A onWindowClosing(final A w, final Object r) { if (w != null) { swing(new Runnable() { public void run() { try { w.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { AutoCloseable __1 = tempRememberListener(w, "removeWindowListener", this); try { pcallF(r); } finally { _close(__1); } } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "w.addWindowListener(new WindowAdapter {\r\n public void windowClosing(Wind..."; } }); } return w; } static Runnable runnableThread(final Runnable r) { return new Runnable() { public void run() { try { startThread(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "startThread(r)"; } }; } // experimental static boolean cleanUp_interruptThreads = false; static void cleanUp(Object c) { if (c == null) return; if (c instanceof AutoCloseable) { close_pcall(((AutoCloseable) c)); return; } if (c instanceof java.util.Timer) { ((java.util.Timer) c).cancel(); return; } if (c instanceof Collection) { cleanUp((Collection) c); return; } if (c instanceof Map) { for (Object o : keys((Map) c)) cleanUp(o); for (Object o : values((Map) c)) cleanUp(o); ((Map) c).clear(); return; } // if (!(c instanceof Class)) ret; try { // revoke license preCleanUp(c); // unpause setOpt(c, "ping_pauseAll", false); // call custom cleanMeUp() and cleanMeUp_*() functions innerCleanUp(c); // Java spec says finalize should only be called by GC, // but we care to differ. // Edit: Not anymore (illegal access warnings) /*if (isTrue(vmMap_get('callFinalize))) pcallOpt(c, "finalize");*/ // remove all virtual bots (hope this works) List androids = (List) getOpt(c, "record_list"); for (Object android : unnull(androids)) // heck we'll dispose anything pcallOpt(android, "dispose"); // sub-cleanup List classes = (List) (getOpt(c, "hotwire_classes")); if (classes != null) for (WeakReference cc : classes) { try { cleanUp(cc.get()); } catch (Throwable __e) { _handleException(__e); } } // interrupt all threads (experimental, they might be doing cleanup?) if (cleanUp_interruptThreads) { List threads = registeredThreads(c); if (nempty(threads)) { print("cleanUp: Interrupting " + n2(threads, "thread") + ": " + joinWithComma(allToString(threads))); interruptThreads(threads); } } } catch (Throwable __e) { _handleException(__e); } setOpt(c, "cleaningUp_flag", false); if (c instanceof Class && ((Class) c).getName().equals("main")) retireClassLoader(((Class) c).getClassLoader()); } static void cleanUp(Collection l) { if (l == null) return; for (Object c : l) cleanUp(c); l.clear(); } static void cleanKillVM() { try { ping(); assertNotOnAWTThread(); cleanKillVM_noSleep(); Object o = new Object(); synchronized (o) { o.wait(); } } catch (Exception __e) { throw rethrow(__e); } } static void cleanKillVM_noSleep() { call(getJavaX(), "cleanKill"); } static JTextArea uneditableBlackTextArea_noUndo() { return uneditableBlackTextArea_noUndo(""); } static JTextArea uneditableBlackTextArea_noUndo(String text) { return makeUneditableWithTextColor(Color.black, jTextArea_noUndo(text)); } static A uneditableBlack(A a) { return makeUneditableWithTextColor(Color.black, a); } static Object swing(Object f) { return swingAndWait(f); } static A swing(F0 f) { return (A) swingAndWait(f); } static A swing(IF0 f) { return (A) swingAndWait(f); } // keyCode = KeyEvent VK_... static void registerCtrlKey(JComponent c, int keyCode, String name, final Runnable r) { Action action = abstractAction(name, r); KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, InputEvent.CTRL_MASK); c.getActionMap().put(name, action); c.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, name); } static void registerCtrlKey(JFrame frame, int keyCode, String name, final Runnable r) { registerCtrlKey(frame.getRootPane(), keyCode, name, r); } // defaults to true static ThreadLocal addMenu_addIfEmpty = new ThreadLocal(); static JMenu addMenu(final Component c, final String menuName, final Object... items) { final RootPaneContainer frame = getPossiblyInternalFrame(c); return (JMenu) swing(new F0() { public Object get() { try { JMenuBar bar = addMenuBar((Component) frame); Pair p = jmenu_autoMnemonic(menuName); JMenu menu = getMenuNamed(bar, p.a); boolean isNew = menu == null; if (isNew) menu = new JMenu(p.a); else menu.removeAll(); menu.setMnemonic(p.b); fillJMenu(menu, items); if (isNew) { if (!isFalse(addMenu_addIfEmpty.get()) || menuItemCount(menu) > 0) { bar.add(menu); revalidate((Component) frame); } } return menu; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JMenuBar bar = addMenuBar((Component) frame);\r\n Pair p = jmenu_aut..."; } }); } // r : runnable or voidfunc(bool) static JCheckBoxMenuItem jCheckBoxMenuItem(String text, boolean checked, final Object r) { final JCheckBoxMenuItem mi = swing(() -> new JCheckBoxMenuItem(text, checked)); addActionListener(mi, new Runnable() { public void run() { try { callF(r, isChecked(mi)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r, isChecked(mi))"; } }); return mi; } static JCheckBoxMenuItem jCheckBoxMenuItem(String text, boolean checked, IVF1 r) { return jCheckBoxMenuItem(text, checked, (Object) r); } static JMenu jMenu(final String title, final Object... items) { return jmenu(title, items); } static void activateConsole() { showConsole(); activateFrame(consoleFrame()); } static void setChecked(JCheckBox checkBox, boolean b) { if (checkBox != null) { swing(new Runnable() { public void run() { try { if (isChecked(checkBox) != b) checkBox.setSelected(b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (isChecked(checkBox) != b)\r\n checkBox.setSelected(b);"; } }); } } static void setChecked(JCheckBoxMenuItem mi, boolean b) { if (mi != null) { swing(new Runnable() { public void run() { try { mi.setSelected(b); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mi.setSelected(b);"; } }); } } static JMenuBar getMenuBar(Component c) { return (JMenuBar) call(getPossiblyInternalFrame(c), "getJMenuBar"); } static JMenuItem jMenuItem(final String text) { return jmenuItem(text); } static JMenuItem jMenuItem(String text, Object r) { return jmenuItem(text, r); } static void addMenuItem(JPopupMenu menu, String text, Object action) { menu.add(jmenuItem(text, action)); } static void addMenuItem(JPopupMenu menu, JMenuItem menuItem) { menu.add(menuItem); } static void addMenuItem(JMenu menu, String text, Object action) { menu.add(jmenuItem(text, action)); } static void addMenuItem(Menu menu, String text, Object action) { menu.add(menuItem(text, action)); } static void addMenuItem(JMenu menu, JMenuItem menuItem) { menu.add(menuItem); } static void addMenuItem(JMenuBar menuBar, String text, Runnable action) { addMenuItem(menuBar, jmenuItem(text, action)); } static void addMenuItem(JMenuBar menuBar, JMenuItem menuItem) { addDirectMenuItem(menuBar, menuItem); } static A jPreferredWidthToMaxWidth(A c) { if (c != null) { swing(new Runnable() { public void run() { try { jMaxWidth(c, preferredWidth(c)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "jMaxWidth(c, preferredWidth(c));"; } }); } return c; } static void addAndRevalidate(Container c, Component x) { addAndValidate(c, x); } static Component jHorizontalGlue() { return swing(() -> Box.createHorizontalGlue()); } // key = 1 to 12 static void registerFunctionKey(JFrame frame, int key, Object r) { String name = "F" + key; Action action = abstractAction(name, r); JComponent pnl = frame.getRootPane(); KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_F1 + key - 1, 0); pnl.getActionMap().put(name, action); pnl.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, name); } // key = KeyEvent.VK_... static void registerKeyCode(JFrame frame, int keyCode, Object r) { String name = "key " + keyCode; Action action = abstractAction(name, r); JComponent pnl = frame.getRootPane(); KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, 0); pnl.getActionMap().put(name, action); pnl.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(keyStroke, name); } static JSpinner jSpinner(final int value) { return swing(new F0() { public JSpinner get() { try { JSpinner s = new JSpinner(); s.setValue(value); return s; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new JSpinner s;\r\n s.setValue(value);\r\n ret s;"; } }); } static JSpinner jSpinner(final int value, final int min, final int max) { return swing(new F0() { public JSpinner get() { try { return new JSpinner(new SpinnerNumberModel(value, min, max, 1)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret new JSpinner(new SpinnerNumberModel(value, min, max, 1));"; } }); } static A onChange(A spinner, Object r) { { swing(new Runnable() { public void run() { try { spinner.addChangeListener(changeListener(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "spinner.addChangeListener(changeListener(r));"; } }); } return spinner; } static A onChange(A b, Object r) { { swing(new Runnable() { public void run() { try { b.addItemListener(itemListener(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "b.addItemListener(itemListener(r));"; } }); } return b; } static void onChange(JTextComponent tc, Object r) { onUpdate(tc, r); } static A onChange(A slider, final Object r) { { swing(new Runnable() { public void run() { try { slider.addChangeListener(changeListener(r)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "slider.addChangeListener(changeListener(r));"; } }); } return slider; } static JComboBox onChange(Object r, JComboBox cb) { return onChange(cb, r); } static JComboBox onChange(JComboBox cb, final Object r) { if (isEditableComboBox(cb)) onChange(textFieldFromComboBox(cb), r); else onSelectedItem(cb, new VF1() { public void get(String s) { try { callF(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(r)"; } }); return cb; } static int intFromSpinner(JSpinner s) { return toInt(s.getValue()); } static int swingShowConfirmDialog(Component owner, String msg, String title, int options) { return swing(() -> JOptionPane.showConfirmDialog(owner, msg, title, options)); } static SingleComponentPanel singleComponentPanel() { return singleComponentPanel(null); } static SingleComponentPanel singleComponentPanel(final Component c) { return swing(new F0() { public SingleComponentPanel get() { try { return new SingleComponentPanel(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret new SingleComponentPanel(c);"; } }); } static JPanel westAndCenterWithMargin(Component w, Component c) { return westAndCenter(withRightMargin(w), c); } static JPanel westAndCenterWithMargin(int margin, Component w, Component c) { return westAndCenter(withRightMargin(margin, w), c); } static JPanel jvstackWithSpacing(List parts, int spacing) { return vstackWithSpacing(parts, spacing); } static JPanel jvstackWithSpacing(int spacing, List parts) { return vstackWithSpacing(parts, spacing); } static JPanel jvstackWithSpacing(int spacing, Component... parts) { return jvstackWithSpacing(asList(parts), spacing); } static JPanel jvstackWithSpacing(List parts) { return vstackWithSpacing(parts); } static JPanel jvstackWithSpacing(Component... parts) { return vstackWithSpacing(parts); } static JComponent withTitle(String title, Component c) { return withTitle(withTitle_titlePanel(title), c); } static JComponent withTitle_titlePanel(String title) { return jlabel(title); } static JPanel withTitle(final JComponent titleComponent, final Component c) { return swing(new F0() { public JPanel get() { try { titleComponent.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIManager.getColor("Button.borderColor"))); JPanel panel = new JPanel(new BorderLayout()); panel.setBackground(Color.WHITE); panel.add(BorderLayout.NORTH, titleComponent); panel.add(BorderLayout.CENTER, wrap(c)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "titleComponent.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIManage..."; } }); } static JButton jbutton(String text, Object action) { return newButton(text, action); } // button without action static JButton jbutton(String text) { return newButton(text, null); } /*static JButton jbutton(BufferedImage img, O action) { ret setButtonImage(img, jbutton("", action)); }*/ static JButton jbutton(Action action) { return swingNu(JButton.class, action); } static JTextField disableTextField(final JTextField tf) { if (tf != null) { swing(new Runnable() { public void run() { try { tf.setEnabled(false); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tf.setEnabled(false);"; } }); } return tf; } static JTextField jLiveValueTextField(final LiveValue lv) { final JTextField tf = jTextField(); bindTextComponentToLiveValue(tf, lv); return tf; } static SimpleLiveValue conceptFieldLiveValue(Concept c, String fieldName) { Class type = getFieldType(c, fieldName); SimpleLiveValue value = new SimpleLiveValue(type, cget(c, fieldName)); // TODO: make mechanism for listening to a single concept onConceptChangeByClass_notOnAllChanged(c.getClass(), new Runnable() { public void run() { try { Object o = cget(c, fieldName); value.set(o); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Object o = cget(c, fieldName);\r\n value.set(o);"; } }); value.onChange(new Runnable() { public void run() { try { cset(c, fieldName, value.get()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cset(c, fieldName, value.get());"; } }); return value; } static SimpleLiveValue conceptFieldLiveValue(String fieldName, Concept c) { return conceptFieldLiveValue(c, fieldName); } static A fontSizePlus(final int delta, final A c) { if (c != null) { swing(new Runnable() { public void run() { try { Font font = c.getFont(); c.setFont(font.deriveFont(font.getSize2D() + delta)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Font font = c.getFont();\r\n c.setFont(font.deriveFont(font.getSize2D()+delt..."; } }); } return c; } static A setForeground(Color color, A a) { if (a != null) a.setForeground(color); return a; } static JLabel jCenteredLabel(String text) { return jcenteredLabel(text); } static JLabel jCenteredLabel() { return jcenteredLabel(); } static JPanel jvgridWithSpacing(Object... _parts) { return vgridWithSpacing(_parts); } static JLabel jLabel(String text) { return jlabel(text); } static JLabel jLabel() { return jlabel(); } static JPanel northAndCenterWithMargin(int margin, Component n, Component c) { return northAndCenter(withBottomMargin(margin, n), c); } static JPanel northAndCenterWithMargin(Component n, Component c) { return northAndCenter(withBottomMargin(n), c); } static int vstackWithSpacing_default = 10; static JPanel vstackWithSpacing(final List parts) { return vstackWithSpacing(parts, vstackWithSpacing_default); } static JPanel vstackWithSpacing(final List parts, final int spacing) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = GridBagConstraints.REMAINDER; // well... gbc.insets = new Insets(spacing / 2, 0, spacing / 2, 0); smartAddWithLayout(panel, gbc, toObjectArray(nonNulls(parts))); // gbc = (GridBagConstraints) gbc.clone(); // gbc.fill = GridBagConstraints.BOTH; gbc.weighty = 1; gbc.insets = new Insets(0, 0, 0, 0); panel.add(jrigid(), gbc); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new GridBagLayout);\r\n new GridBagConstraints gbc..."; } }); } static JPanel vstackWithSpacing(Component... parts) { return vstackWithSpacing(asList(parts), vstackWithSpacing_default); } static JPanel vstackWithSpacing(int spacing, Component... parts) { return vstackWithSpacing(asList(parts), spacing); } static JLabel jlabel(final String text) { return swingConstruct(BetterLabel.class, text); } static JLabel jlabel() { return jlabel(" "); } static A jMinHeight(A c, int h) { return jMinHeight(h, c); } static A jMinHeight(int h, A c) { Dimension size = c.getMinimumSize(); c.setMinimumSize(new Dimension(size.width, max(h, size.height))); return jPreferHeight(h, c); } static int swingScale(double x) { return iround(swingFontScale() * x); } static JPanel jCenteredSection(Component c) { return jCenteredSection("", c); } static JPanel jCenteredSection(String title, Swingable c) { return jCenteredSection(title, wrap(c)); } static JPanel jCenteredSection(String title, Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = jSection(title, c); ((TitledBorder) p.getBorder()).setTitleJustification(TitledBorder.CENTER); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = jSection(title, c);\r\n ((TitledBorder) p.getBorder()).setTitleJu..."; } }); } static JPanel jCenteredSection(String title) { return jCenteredSection(title, jpanel()); } static JPanel jflow(Object... components) { JPanel panel = new JPanel(new FlowLayout()); smartAdd(panel, components); return panel; } static JButton jButton(String text, Object action) { return newButton(text, action); } // button without action static JButton jButton(String text) { return newButton(text, null); } static JButton jButton(BufferedImage img, Object action) { return setButtonImage(img, jbutton("", action)); } static JButton jButton(Action action) { return swingNu(JButton.class, action); } static void killVM() { cleanKillVM(); } static boolean killVM(int port) { return eq("ok", sendToLocalBot(port, "kill")); } static JPanel westAndCenterWithMargins(Component w, Component c) { return applyDefaultMargin(westAndCenter(withRightMargin(w), c)); } static JPanel westAndCenterWithMargins(int margin, Component w, Component c) { return addMargin(margin, westAndCenter(withRightMargin(margin, w), c)); } static A jFixedSize(final int w, final A c) { return jFixedSize(w, w, c); } static A jFixedSize(final int w, final int h, final A c) { if (c != null) { swing(new Runnable() { public void run() { try { Dimension d = new Dimension(w, h); c.setMinimumSize(d); c.setPreferredSize(d); c.setMaximumSize(d); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Dimension d = new Dimension(w, h);\r\n c.setMinimumSize(d);\r\n c.setPrefer..."; } }); } return c; } static A jFixedSize(final A c, Dimension d) { return jFixedSize(d.width, d.height, c); } static void setFrameContents(final Component c, final Object contents) { swing(new Runnable() { public void run() { try { JFrame frame = getFrame(c); if (frame == null) return; frame.getContentPane().removeAll(); frame.getContentPane().setLayout(new BorderLayout()); frame.getContentPane().add(wrap(contents)); revalidate(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JFrame frame = getFrame(c);\r\n if (frame == null) return;\r\n frame.getContent..."; } }); } // x = names and components interleaving. // or just components. // or just names. // also, first element can be index of tab to open at start // also, SUPER short demo syntax: jtabs(3) // also, you can pass a Collection containing the elements static JTabbedPane jtabs(Object... x) { return fillJTabs(swingNu(JTabbedPane.class), x); } static void centerPackFrame(Component c) { centerPackedFrame(c); } static A jMinWidth_pure(int w, A c) { { swing(new Runnable() { public void run() { try { Dimension size = c.getMinimumSize(); c.setMinimumSize(new Dimension(w, size.height)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Dimension size = c.getMinimumSize();\r\n c.setMinimumSize(new Dimension(w, s..."; } }); } return c; } static A jMinWidth_pure(A c, int w) { return jMinWidth_pure(w, c); } static int max(int a, int b) { return Math.max(a, b); } static int max(int a, int b, int c) { return max(max(a, b), c); } static long max(int a, long b) { return Math.max((long) a, b); } static long max(long a, long b) { return Math.max(a, b); } static double max(int a, double b) { return Math.max((double) a, b); } static float max(float a, float b) { return Math.max(a, b); } static double max(double a, double b) { return Math.max(a, b); } static int max(Collection c) { int x = Integer.MIN_VALUE; for (int i : c) x = max(x, i); return x; } static double max(double[] c) { if (c.length == 0) return Double.MIN_VALUE; double x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static float max(float[] c) { if (c.length == 0) return Float.MAX_VALUE; float x = c[0]; for (int i = 1; i < c.length; i++) x = Math.max(x, c[i]); return x; } static byte max(byte[] c) { byte x = -128; for (byte d : c) if (d > x) x = d; return x; } static short max(short[] c) { short x = -0x8000; for (short d : c) if (d > x) x = d; return x; } static int max(int[] c) { int x = Integer.MIN_VALUE; for (int d : c) if (d > x) x = d; return x; } static A centerFrameWithMinWidth(A c) { JFrame f = getFrame(c); if (f != null) centerFrameWithWidth(getMinimumWidth(f), f); return c; } static A jMinHeight_pure(int h, A c) { { swing(new Runnable() { public void run() { try { Dimension size = c.getMinimumSize(); c.setMinimumSize(new Dimension(size.width, h)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Dimension size = c.getMinimumSize();\r\n c.setMinimumSize(new Dimension(size..."; } }); } return c; } static A jMinHeight_pure(A c, int h) { return jMinHeight_pure(h, c); } static boolean isProgramID(String snippetID) { return amProgram(snippetID); } // f must return a list static List concatMap(Object f, Iterable l) { return concatLists(map(f, l)); } static List concatMap(Iterable l, Object f) { return concatMap(f, l); } static List concatMap(Object f, Object[] l) { return concatLists(map(f, l)); } static List concatMap(Object[] l, Object f) { return concatMap(f, l); } static > List concatMap(Iterable l, IF1 f) { return concatMap(l, (Object) f); } static > List concatMap(IF1 f, Iterable l) { return concatMap(l, f); } static List allChildrenOfType(Component c, Class theClass) { return childrenOfType(c, theClass); } static List allChildrenOfType(Class theClass, Component c) { return childrenOfType(theClass, c); } static boolean isInstanceOfAny(Object o, Collection b) { return any(b, x -> isInstanceOf(o, x)); } static boolean isInstanceOfAny(Object o, Class... b) { return any(b, x -> isInstanceOf(o, x)); } static A setEnabled(A c, boolean enable) { if (c != null) { swing(new Runnable() { public void run() { try { c.setEnabled(enable); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setEnabled(enable);"; } }); } return c; } static A setEnabled(boolean enable, A c) { return setEnabled(c, enable); } static boolean preferCached = false; static boolean loadSnippet_debug = false; static ThreadLocal loadSnippet_silent = new ThreadLocal(); static ThreadLocal loadSnippet_publicOnly = new ThreadLocal(); static int loadSnippet_timeout = 30000; static String loadSnippet(String snippetID) { try { if (snippetID == null) return null; return loadSnippet(parseSnippetID(snippetID), preferCached); } catch (Exception __e) { throw rethrow(__e); } } static String loadSnippet(String snippetID, boolean preferCached) throws IOException { return loadSnippet(parseSnippetID(snippetID), preferCached); } static IF1 loadSnippet; static String loadSnippet(long snippetID) { return loadSnippet != null ? loadSnippet.get(snippetID) : loadSnippet_base(snippetID); } final static String loadSnippet_fallback(IF1 _f, long snippetID) { return _f != null ? _f.get(snippetID) : loadSnippet_base(snippetID); } static String loadSnippet_base(long snippetID) { try { return loadSnippet(snippetID, preferCached); } catch (Exception __e) { throw rethrow(__e); } } static String loadSnippet(long snippetID, boolean preferCached) throws IOException { if (isLocalSnippetID(snippetID)) return loadLocalSnippet(snippetID); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadSnippet(fsI(snippetID)); return loadSnippet_noResourceLoader(snippetID, preferCached); } static String loadSnippet_noResourceLoader(long snippetID, boolean preferCached) throws IOException { String text; // boss bot (old concept) /*text = getSnippetFromBossBot(snippetID); if (text != null) return text;*/ initSnippetCache(); text = DiskSnippetCache_get(snippetID); if (preferCached && text != null) return text; try { if (loadSnippet_debug && text != null) System.err.println("md5: " + md5(text)); String url = tb_mainServer() + "/getraw.php?id=" + snippetID + "&utf8=1"; if (nempty(text)) url += "&md5=" + md5(text); if (!isTrue(loadSnippet_publicOnly.get())) url += standardCredentials(); String text2 = loadSnippet_loadFromServer(url); boolean same = eq(text2, "==*#*=="); if (loadSnippet_debug) print("loadSnippet: same=" + same); if (!same) text = text2; } catch (RuntimeException e) { e.printStackTrace(); throw new IOException("Snippet #" + snippetID + " not found or not public"); } try { initSnippetCache(); DiskSnippetCache_put(snippetID, text); } catch (IOException e) { System.err.println("Minor warning: Couldn't save snippet to cache (" + DiskSnippetCache_getDir() + ")"); } return text; } static File DiskSnippetCache_dir; public static void initDiskSnippetCache(File dir) { DiskSnippetCache_dir = dir; dir.mkdirs(); } public static synchronized String DiskSnippetCache_get(long snippetID) throws IOException { return loadTextFile(DiskSnippetCache_getFile(snippetID).getPath(), null); } private static File DiskSnippetCache_getFile(long snippetID) { return new File(DiskSnippetCache_dir, "" + snippetID); } public static synchronized void DiskSnippetCache_put(long snippetID, String snippet) throws IOException { saveTextFile(DiskSnippetCache_getFile(snippetID).getPath(), snippet); } public static File DiskSnippetCache_getDir() { return DiskSnippetCache_dir; } public static void initSnippetCache() { if (DiskSnippetCache_dir == null) initDiskSnippetCache(getGlobalCache()); } static String loadSnippet_loadFromServer(String url) { Integer oldTimeout = setThreadLocal(loadPage_forcedTimeout_byThread, loadSnippet_timeout); try { return isTrue(loadSnippet_silent.get()) ? loadPageSilently(url) : loadPage(url); } finally { loadPage_forcedTimeout_byThread.set(oldTimeout); } } static String firstLine(String text) { if (text == null) return null; int i = text.indexOf('\n'); return i >= 0 ? text.substring(0, i) : text; } static String dropFirstLine(String text) { if (text == null) return null; int i = text.indexOf('\n'); return i >= 0 ? text.substring(i + 1) : ""; } static JFrame showCenterFrame(String title, int w, int h) { return showCenterFrame(title, w, h, null); } static JFrame showCenterFrame(Pt size, Component content) { return showCenterFrame(size, defaultFrameTitle(), content); } static JFrame showCenterFrame(Pt size, String title, Component content) { return showCenterFrame(title, size.x, size.y, content); } static JFrame showCenterFrame(int w, int h, Component content) { return showCenterFrame(defaultFrameTitle(), w, h, content); } static JFrame showCenterFrame(String title, int w, int h, Component content) { JFrame frame = makeFrame(title, content); setSize(frame, w, h); return centerFrame(frame); } static JFrame showCenterFrame(int w, int h, String title, Component content) { return showCenterFrame(title, w, h, content); } static JFrame showCenterFrame(String title, Component content) { return centerFrame(makeFrame(title, content)); } static JFrame showCenterFrame(Component content) { return centerFrame(makeFrame(content)); } static A makeUneditableWithTextColor(A a, Color color) { if (a != null) { swing(new Runnable() { public void run() { try { a.setEditable(false); a.setDisabledTextColor(color); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.setEditable(false);\r\n a.setDisabledTextColor(color);"; } }); } return a; } static A makeUneditableWithTextColor(Color color, A a) { return makeUneditableWithTextColor(a, color); } static JTextArea wordWrapTextArea() { return wrappedTextArea(); } static JTextArea wordWrapTextArea(String text) { return wrappedTextArea(text); } static JTextArea wordWrapTextArea(JTextArea ta) { enableWordWrapForTextArea(ta); return ta; } static Font sansSerifFont(int fontSize) { return sansSerif(fontSize); } static JFrame getFrame(final Object _o) { return swing(new F0() { public JFrame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof JFrame) return (JFrame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n if (o instanceof ButtonGroup) o = first(buttonsInGroup((Button..."; } }); } static Pt maxPt(Pt a, Pt b) { return a == null ? b : b == null ? a : new Pt(max(a.x, b.x), max(a.y, b.y)); } static Pt scalePt(Pt p, double f) { return new Pt(iround(p.x * f), iround(p.y * f)); } static Pt scalePt(double f, Pt p) { return scalePt(p, f); } static Pt scalePt(int w, int h, double f) { return scalePt(new Pt(w, h), f); } static boolean swingFontScale_debug = false; static void swingFontScale(double scale) { swingFontScale((float) scale); } static void swingFontScale(float scale) { swing(new Runnable() { public void run() { try { vm_generalMap_set("swingFontScale_value", scale); Map swingFontScale_originals = (Map) (vm_generalMap_get("swingFontScale_originals")); if (swingFontScale_originals == null) { vm_generalMap_set("swingFontScale_originals", swingFontScale_originals = new HashMap()); for (Map.Entry entry : UIManager.getDefaults().entrySet()) { Object key = entry.getKey(); if (key.toString().toLowerCase().contains(".font")) { Object value = entry.getValue(); Font font = null; if (swingFontScale_debug) print("swingFontScale found value: " + key + " = " + value); if (value instanceof UIDefaults.LazyValue) value = ((UIDefaults.LazyValue) value).createValue(UIManager.getDefaults()); else if (value instanceof UIDefaults.ActiveValue) // ActiveValue is supposed to create the value every time but we ignore that. Hopefully this works anyway. value = ((UIDefaults.ActiveValue) value).createValue(UIManager.getDefaults()); if (value instanceof Font) swingFontScale_originals.put(key.toString(), ((Font) value)); } } } for (Map.Entry __0 : _entrySet(swingFontScale_originals)) { String key = __0.getKey(); Font font = __0.getValue(); Font font2 = font.deriveFont(Font.PLAIN, font.getSize() * scale); if (swingFontScale_debug) print("swingFontScale " + scale + ": Setting " + key + " = " + font2); UIManager.put(key, font2); } // revalidateAllFrames(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "vm_generalMap_set(\"swingFontScale_value\", scale);\r\n Map swingF..."; } }); } static float swingFontScale() { return getSwingFontScale(); } static int withMargin_defaultWidth = 6; static JPanel withMargin(Component c) { return withMargin(withMargin_defaultWidth, c); } static JPanel withMargin(int w, Component c) { return withMargin(w, w, c); } static JPanel withMargin(int w, int h, Component c) { return withMargin(w, h, w, h, c); } static JPanel withMargin(final int top, final int left, final int bottom, final int right, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(top, left, bottom, right)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static JPanel centerAndSouthWithMargin(Component c, Component s) { return centerAndSouth(c, withTopMargin(s)); } static JPanel centerAndSouthWithMargin(int margin, Component c, Component s) { return centerAndSouth(c, withTopMargin(margin, s)); } static A setFont(final Font font, final A a) { if (a != null) { swing(new Runnable() { public void run() { try { a.setFont(font); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.setFont(font);"; } }); } return a; } static A setFont(A a, Font font) { return setFont(font, a); } static A setFont(final String fontID, float fontSize, final A a) { return setFont(loadFont_cached(fontID, fontSize), a); } static A topAlignLabel(A a) { return verticalAlignTop(a); } static A topAlignLabel(A a) { return verticalAlignTop(a); } static JLabel jMultiLineLabel(String text) { return jTopLabel(jlabel_textAsHTML(text)); } static String linesLL(Object... x) { return lines(ll(x)); } static JPanel centerAndEastWithMargin(Component c, Component e) { return centerAndEastWithMarginInbetween(c, e); } static void frameToFront(Component c) { activateFrame(c); } static Font typeWriterFont() { return typeWriterFont(iround(14 * getSwingFontScale())); } static Font typeWriterFont(int size) { return new Font("Courier", Font.PLAIN, size); } static JSplitPane jvsplit(Component n, Component s) { return jvsplit(n, s, 0.5); } static JSplitPane jvsplit(Component n, Component s, double splitPoint) { return jvsplit(n, s, splitPoint, 0); } static JSplitPane jvsplit(Component n, Component s, double splitPoint, int delay) { return setSplitPaneOnFirstShowing(swingNu(JSplitPane.class, JSplitPane.VERTICAL_SPLIT, wrap(n), wrap(s)), splitPoint, delay); } static JSplitPane jvsplit(double splitPoint, Component n, Component s) { return jvsplit(splitPoint, 0, n, s); } static JSplitPane jvsplit(double splitPoint, int delay, Component n, Component s) { return jvsplit(n, s, splitPoint, delay); } static JPanel centerAndEastWithMargins(Component c, Component e) { return applyDefaultMargin(centerAndEast(c, withLeftMargin(e))); } static JRadioButton jradiobutton(String text, ButtonGroup group) { return swing(new F0() { public JRadioButton get() { try { JRadioButton rb = new JRadioButton(text); if (group != null) group.add(rb); return rb; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JRadioButton rb = new JRadioButton(text);\r\n if (group != null) group.add(r..."; } }); } static JRadioButton jradiobutton(ButtonGroup group, String text) { return jradiobutton(text, group); } static JRadioButton jradiobutton(ButtonGroup group, String text, boolean selected) { var rb = jradiobutton(group, text); if (selected) selectRadioButton(rb); return rb; } static boolean isChecked(JCheckBox checkBox) { return checkBox != null && (boolean) swing(new F0() { public Boolean get() { try { return checkBox.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret checkBox.isSelected();"; } }); } static boolean isChecked(JCheckBoxMenuItem mi) { return mi != null && (boolean) swing(new F0() { public Boolean get() { try { return mi.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret mi.isSelected();"; } }); } static boolean isChecked(JRadioButton rb) { return rb != null && (boolean) swing(() -> rb.isSelected()); } static void addActionListener(JTextField tf, final Runnable action) { onEnter(tf, action); } static void addActionListener(final JComboBox cb, final Runnable action) { if (cb != null) { swing(new Runnable() { public void run() { try { cb.addActionListener(actionListener(action)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cb.addActionListener(actionListener(action));"; } }); } } static void addActionListener(final AbstractButton b, final Runnable action) { if (b != null) { swing(new Runnable() { public void run() { try { b.addActionListener(actionListener(action)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "b.addActionListener(actionListener(action));"; } }); } } static boolean confirmOKCancel(final Component owner, final String msg) { return isTrue(swingAndWait(new F0() { public Object get() { try { return JOptionPane.showConfirmDialog(owner, msg, "JavaX", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.OK_OPTION; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret JOptionPane.showConfirmDialog(owner,\r\n msg, \"JavaX\", JOptionPane.OK_..."; } })); } static boolean confirmOKCancel(String msg) { return confirmOKCancel(null, msg); } static int hstackWithSpacing_spacing = 10; // first part can be spacing value static JPanel hstackWithSpacing(Object... parts) { // allow collections in parameters parts = flattenArray2(parts); int spacing = hstackWithSpacing_spacing; int i = 0; if (first(parts) instanceof Integer) { spacing = toInt(first(parts)); ++i; } JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.weighty = 1; gbc.fill = GridBagConstraints.VERTICAL; gbc.gridheight = GridBagConstraints.REMAINDER; for (; i < l(parts); i++) { if (i != 0) panel.add(javax.swing.Box.createRigidArea(new Dimension(spacing, 0)), gbc); panel.add(wrapForSmartAdd(parts[i]), gbc); } gbc.weightx = 1; panel.add(jrigid(), gbc); return panel; } static A jMinWidth(final int w, final A c) { if (c == null) return null; return swing(new F0() { public A get() { try { Dimension size = c.getMinimumSize(); c.setMinimumSize(new Dimension(/*max(w, size.width) ??? */ w, size.height)); return jPreferWidth(w, c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Dimension size = c.getMinimumSize();\r\n c.setMinimumSize(new Dimension(/*ma..."; } }); } static JComponent withLabel(String label, JComponent component) { return westAndCenter(jlabel(label + " "), component); } static JComponent withLabel(JComponent label, JComponent component) { return westAndCenterWithMargin(label, component); } static A bindTextComponentToLiveValue(final A tc, final LiveValue lv) { return bindLiveValueListenerToComponent(tc, lv, new Runnable() { public void run() { try { setText(tc, strOrNull(lv.get())); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "setText(tc, strOrNull(lv.get()))"; } }); } static A bindTextComponentToLiveValue(LiveValue lv, A tc) { return bindTextComponentToLiveValue(tc, lv); } static ButtonGroup buttonGroup() { return new ButtonGroup(); } static JPanel northAndCenterWithMargins(Component n, Component c) { return applyDefaultMargin(northAndCenter(withBottomMargin(n), c)); } static JPanel northAndCenterWithMargins(int margin, Component n, Component c) { return applyMargin(margin, northAndCenter(withBottomMargin(margin, n), c)); } static int withLeftMargin_defaultWidth = 6; static JPanel withLeftMargin(Component c) { return withLeftMargin(withLeftMargin_defaultWidth, c); } static JPanel withLeftMargin(final int margin, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(0, margin, 0, 0)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static List itemPlus(A a, Collection l) { return itemPlusList(a, l); } static JCheckBox jCheckBox() { return swingNu(JCheckBox.class); } static JCheckBox jCheckBox(boolean checked) { return swingNu(JCheckBox.class, "", checked); } static JCheckBox jCheckBox(String text, boolean checked) { return swingNu(JCheckBox.class, text, checked); } static JCheckBox jCheckBox(String text) { return swingNu(JCheckBox.class, text); } static JCheckBox jCheckBox(String text, boolean checked, final Object onChange) { JCheckBox cb = jCheckBox(checked, onChange); cb.setText(text); return cb; } // onChange can be a Runnable or a voidfunc(bool) static JCheckBox jCheckBox(boolean checked, final Object onChange) { final JCheckBox cb = jCheckBox(checked); cb.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { pcallF(onChange, cb.isSelected()); } }); return cb; } static void addOrRemove(Collection c, A a, boolean add) { if (add) c.add(a); else c.remove(a); } static JPanel jvstack(Object... parts) { return vstack(parts); } static JPanel jvstack(List parts) { return vstack(parts); } static String unindentMLS(String s) { return autoUnindent_mls(s); } static Component verticalStrut(int height) { return Box.createVerticalStrut(height); } static JFrame showPackedFrame(String title, Component contents) { return packFrame(showFrame(title, contents)); } static JFrame showPackedFrame(Component contents) { return packFrame(showFrame(contents)); } static JLabel jTopLabel(final String text) { return jtoplabel(text); } static JLabel jTopLabel() { return jtoplabel(); } static String hhtml(Object contents) { return containerTag("html", contents); } static String nlToBr(String s) { return s.replace("\n", "
\n"); } static String mls_replaceDollarVars(String s, Object... params) { return replaceDollarVars_unindentMLS(s, params); } static String himgForJLabel(String src, Object... params) { return jlabel_fixImages(tag("img", "", arrayPlus(params, "src", src))); } static JFrame showPackedFrameMinWidth(int w, Component c) { return showPackedFrameMinWidth(w, defaultFrameTitle(), c); } static JFrame showPackedFrameMinWidth(int w, String title, Component c) { JFrame f = showPackedFrame(title, c); frameMinWidth(f, w); return f; } static JPanel centeredButtons(Object... params) { return jcenteredbuttons(params); } static String replaceDollarVars(String s, Object... params) { if (empty(params)) return s; Map vars = mapKeys(__38 -> dropDollarPrefix(__38), (Map) litcimap(params)); return replaceDollarVars_dyn(s, var -> strOrNull(vars.get(var))); } static String lines(Iterable lines) { return fromLines(lines); } static String lines(Object[] lines) { return fromLines(asList(lines)); } static List lines(String s) { return toLines(s); } /** * writes safely (to temp file, then rename) */ static File saveTextFile(String fileName, String contents) throws IOException { CriticalAction action = beginCriticalAction("Saving file " + fileName + " (" + l(contents) + " chars)"); try { File file = new File(fileName); mkdirsForFile(file); String tempFileName = fileName + "_temp"; File tempFile = new File(tempFileName); if (contents != null) { if (tempFile.exists()) try { String saveName = tempFileName + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8"); PrintWriter printWriter = new PrintWriter(outputStreamWriter); printWriter.print(contents); printWriter.close(); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (contents != null) if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); vmBus_send("wroteFile", file); return file; } finally { action.done(); } } static File saveTextFile(File fileName, String contents) { try { saveTextFile(fileName.getPath(), contents); return fileName; } catch (Exception __e) { throw rethrow(__e); } } static JWindow infoBox(String text) { return infoMessage(text); } static JWindow infoBox(String text, double seconds) { return infoMessage(text, seconds); } static JWindow infoBox(Throwable e) { return infoMessage(e); } static String fileName(File f) { return f == null ? null : f.getName(); } static String fileNameWithoutExtension(File f) { return dropExtension(fileName(f)); } static void removeAndPut(Map map, A key, B value) { if (map != null) { map.remove(key); map.put(key, value); } } static List linesFromFile_list(File f) { try { return asList_closeIterator(linesFromFile(f)); } catch (Exception __e) { throw rethrow(__e); } } static List linesFromFile_list(String path) { return linesFromFile_list(newFile(path)); } static boolean eqAfterRtrim(String a, String b) { return eq(rtrim(a), rtrim(b)); } static int parseInt(String s) { return emptyString(s) ? 0 : Integer.parseInt(s); } static int parseInt(char c) { return Integer.parseInt(str(c)); } static void messageBox(final String msg) { if (headless()) print(msg); else { swing(new Runnable() { public void run() { try { JOptionPane.showMessageDialog(null, msg, "JavaX", JOptionPane.INFORMATION_MESSAGE); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JOptionPane.showMessageDialog(null, msg, \"JavaX\", JOptionPane.INFORMATION_MES..."; } }); } } static void messageBox(Throwable e) { // showConsole(); printStackTrace(e); messageBox(hideCredentials(innerException2(e))); } static File defaultExtension(String ext, File file) { if (empty(ext)) return file; if (file == null || fileHasAnyExtensionAtAll(file)) return file; return appendToFileName(addDotPrefix(ext), file); } static String defaultExtension(String ext, String fileName) { if (empty(ext)) return fileName; if (fileName == null || contains(fileName, '.')) return fileName; return rjoin(addDotPrefix(ext), fileName); } static Map> callF_cache = newDangerousWeakHashMap(); static
A callF(F0 f) { return f == null ? null : f.get(); } static B callF(F1 f, A a) { return f == null ? null : f.get(a); } static A callF(IF0 f) { return f == null ? null : f.get(); } static B callF(IF1 f, A a) { return f == null ? null : f.get(a); } static C callF(IF2 f, A a, B b) { return f == null ? null : f.get(a, b); } static void callF(VF1 f, A a) { if (f != null) f.get(a); } static Object callF(Object f, Object... args) { if (f instanceof String) // possible SLOWDOWN over callMC return callMCWithVarArgs((String) f, args); return safeCallF(f, args); } static Object safeCallF(Object f, Object... args) { if (f instanceof Runnable) { ((Runnable) f).run(); return null; } if (f == null) return null; Class c = f.getClass(); ArrayList methods; synchronized (callF_cache) { methods = callF_cache.get(c); if (methods == null) methods = callF_makeCache(c); } int n = l(methods); if (n == 0) { throw fail("No get method in " + getClassName(c)); } if (n == 1) return invokeMethod(methods.get(0), f, args); for (int i = 0; i < n; i++) { Method m = methods.get(i); if (call_checkArgs(m, args, false)) return invokeMethod(m, f, args); } throw fail("No matching get method in " + getClassName(c)); } // used internally static ArrayList callF_makeCache(Class c) { ArrayList l = new ArrayList(); Class _c = c; do { for (Method m : _c.getDeclaredMethods()) if (m.getName().equals("get")) { makeAccessible(m); l.add(m); } if (!l.isEmpty()) break; _c = _c.getSuperclass(); } while (_c != null); callF_cache.put(c, l); return l; } static File mkdirs(File dir) { if (dir != null) dir.mkdirs(); return dir; } static File mkdirs(String dir) { return mkdirs(newFile(dir)); } static File userDir() { return new File(userHome()); } static File userDir(String path) { return new File(userHome(), path); } static String[] dropFirst(int n, String[] a) { return drop(n, a); } static String[] dropFirst(String[] a) { return drop(1, a); } static Object[] dropFirst(Object[] a) { return drop(1, a); } static List dropFirst(List l) { return dropFirst(1, l); } static List dropFirst(int n, Iterable i) { return dropFirst(n, toList(i)); } static List dropFirst(Iterable i) { return dropFirst(toList(i)); } static List dropFirst(int n, List l) { return n <= 0 ? l : new ArrayList(l.subList(Math.min(n, l.size()), l.size())); } static List dropFirst(List l, int n) { return dropFirst(n, l); } static String dropFirst(int n, String s) { return substring(s, n); } static String dropFirst(String s, int n) { return substring(s, n); } static String dropFirst(String s) { return substring(s, 1); } static String escapeNewLines(String s) { return s == null ? null : fixNewLines(s).replace("\n", " | "); } static List cdelete(Class c, Object... params) { return deleteConcepts(c, params); } static void cdelete(Concept c) { deleteConcept(c); } static void cdelete(Collection c) { for (A a : cloneList(c)) cdelete(a); } static Concept cnew(String name, Object... values) { return cnew(db_mainConcepts(), name, values); } static Concept cnew(Concepts concepts, String name, Object... values) { Class cc = findClass(name); concepts_unlisted.set(true); Concept c; try { c = cc != null ? nuObject(cc) : new Concept(name); } finally { concepts_unlisted.set(null); } concepts.register(c); csetAll(c, values); return c; } static A cnew(Class cc, Object... values) { return cnew(db_mainConcepts(), cc, values); } static A cnew(Concepts concepts, Class cc, Object... values) { concepts_unlisted.set(true); A c; try { c = nuObject(cc); } finally { concepts_unlisted.set(null); } concepts.register(c); csetAll(c, values); return c; } static String[] asStringArray(Collection c) { return toStringArray(c); } static String[] asStringArray(Object o) { return toStringArray(o); } static List itemPlusList(A a, Collection l) { return concatLists(ll(a), l); } static File newFile(File base, String... names) { for (String name : names) base = new File(base, name); return base; } static File newFile(String name) { return name == null ? null : new File(name); } static File newFile(String base, String... names) { return newFile(newFile(base), names); } static String sanitizeFileName(String s) { return nohup_sanitize(s); } static String simpleDateFormat_defaultTZ_now(String format) { return simpleDateFormat_defaultTZ(format).format(now()); } static A frameTitle(A c, String title) { return setFrameTitle(c, title); } static A frameTitle(String title, A c) { return setFrameTitle(c, title); } static String frameTitle(Component c) { return getFrameTitle(c); } static List mapWithIndexStartingAt1(Collection l, IF2 f) { int n = l(l), i = 0; List out = emptyList(n); for (A a : unnull(l)) out.add(f.get(++i, a)); return out; } static List reversed(Iterable l) { return reversedList(l); } static List reversed(A[] l) { return reversedList(asList(l)); } static String reversed(String s) { return reversedString(s); } static Set keys(Map map) { return map == null ? new HashSet() : map.keySet(); } // convenience shortcut for keys_gen static Set keys(Object map) { return keys((Map) map); } static Set keys(MultiSet ms) { return ms.keySet(); } static Set evalWithTimeout_inTime = synchroSet(); static Set evalWithTimeout_allThreads = newWeakHashSet(); static ThreadLocal evalWithTimeout_threadName = new ThreadLocal(); // Either calculation result or Thread with timed-out computation // Tries to interrupt thread after timeout // Errors are rethrown. static Either evalWithTimeout(int timeoutMS, final Object r) { final Flag done = new Flag(); final Flag doneWaiting = new Flag(); final Var var = new Var(); final Var error = new Var(); Thread t = newThread(getAndClearThreadLocal(evalWithTimeout_threadName), new Runnable() { public void run() { try { try { try { var.set(callF(r)); } finally { evalWithTimeout_allThreads.remove(currentThread()); } } catch (Throwable e) { error.set(e); if (doneWaiting.isUp()) printStackTrace_inPossiblyCancelledThread(e); } finally { done.raise(); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "try {\r\n try {\r\n var.set(callF(r));\r\n } finally {\r\n ev..."; } }); beforeDelegatingToThread(t); try { startThread(t); evalWithTimeout_inTime.add(t); evalWithTimeout_allThreads.add(t); try { done.waitUntilUp(timeoutMS); doneWaiting.raise(); } finally { evalWithTimeout_inTime.remove(t); } // timeout! cancel/interrupt and return thread object if (!done.isUp()) { print("Cancelling thread (timeout)"); cancelAndInterruptThread(t); return either2(t); } // thread ended with error if (error.get() != null) rethrow(error.get()); // thread ended naturally return either1(var.get()); } finally { afterDelegatingToThread(t); } } static Either evalWithTimeout(double timeoutSeconds, final Object r) { return evalWithTimeout(toMS_int(timeoutSeconds), r); } static boolean warn_on = true; static ThreadLocal> warn_warnings = new ThreadLocal(); static void warn(String s) { if (warn_on) print("Warning: " + s); } static void warn(String s, List warnings) { warn(s); if (warnings != null) warnings.add(s); addToCollection(warn_warnings.get(), s); } static char charPlus(char a, int b) { return (char) (((int) a) + b); } static char charPlus(int b, char a) { return charPlus(a, b); } static A withTypeWriterFont(A c) { return setFont(c, typeWriterFont()); } static JPanel jhgridWithSpacing(Object... parts) { return hgridWithSpacing(parts); } static JPanel vstack(Object... parts) { return vstack2(parts); } static JPanel vstack(List parts) { return vstack(toObjectArray(parts)); } public static String rtrim(String s) { if (s == null) return null; int i = s.length(); while (i > 0 && " \t\r\n".indexOf(s.charAt(i - 1)) >= 0) --i; return i < s.length() ? s.substring(0, i) : s; } static int intMax(Collection c, String field) { int max = Integer.MIN_VALUE; for (Object o : c) max = Math.max(max, toInt(getOpt(o, field))); return max; } static int intMax(Iterable l) { int max = Integer.MIN_VALUE; for (int i : unnull(l)) max = Math.max(max, i); return max; } static int intMax(int... l) { int max = Integer.MIN_VALUE; if (l != null) for (int i : l) max = Math.max(max, i); return max; } static String pad(Object s, int l) { return pad(s, l, ' '); } static String pad(Object s, int l, char c) { String _s = str(s); if (lengthOfString(_s) >= l) return _s; return rep(c, l - lengthOfString(_s)) + _s; } static String pad(int l, Object s) { return pad(s, l); } static float toFloat(Object o) { if (o == null) return 0f; if (o instanceof Number) return ((Number) o).floatValue(); if (o instanceof Boolean) return ((Boolean) o).booleanValue() ? 1f : 0f; throw fail("Not convertible to float: " + _getClass(o)); } static void restart() { Object j = getJavaX(); call(j, "cleanRestart", get(j, "fullArgs")); } static File programFile(String name) { return prepareProgramFile(name); } static File programFile(String progID, String name) { return prepareProgramFile(progID, name); } static String dropLeadingEmptyLines(String s) { return regexpReplace_direct(s, "^[ \t \r \n]*\n", ""); } static List splitAtMultipleEqualsLines(String s) { return splitAtLinePredicate("isMultipleEqualsLine", s); } static A assertEqualsVerbose(Object x, A y) { assertEqualsVerbose((String) null, x, y); return y; } // x = expected, y = actual static A assertEqualsVerbose(String msg, Object x, A y) { if (!eq(x, y)) { throw fail((msg != null ? msg + ": " : "") + "expected: " + x + ", got: " + y); } else print("OK" + (empty(msg) ? "" : " " + msg) + ": " + /*sfu*/ (x)); return y; } static void assertEqualsVerbose(Scorer scorer, Object x, Object y) { if (scorer == null) { assertEqualsVerbose(x, y); return; } if (!eq(x, y)) { print(/*sfu*/ (y) + " != " + /*sfu*/ (x)); scorer.add(false); } else { print("OK: " + /*sfu*/ (x)); scorer.add(true); } } static List subList(List l, int startIndex) { return subList(l, startIndex, l(l)); } static List subList(int startIndex, int endIndex, List l) { return subList(l, startIndex, endIndex); } static List subList(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = Math.max(0, startIndex); endIndex = Math.min(n, endIndex); if (startIndex >= endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return l.subList(startIndex, endIndex); } static List getMulti(List l, List indices) { return listGetMulti(l, indices); } static List getMulti(List l, int... indices) { return listGetMulti(l, asList(indices)); } static void printAsciiHeading(String text) { print(asciiHeading2(text)); } static A addAndReturn(Collection c, A a) { if (c != null) c.add(a); return a; } static boolean allStringsEmpty(Iterable l) { return all(__39 -> empty(__39), l); } static String nOutputs(long n) { return n2(n, "output"); } static String nOutputs(Collection l) { return nOutputs(l(l)); } static String nOutputs(Map map) { return nOutputs(l(map)); } static List nempties(Collection c) { return filterNempty(c); } static String getText(final AbstractButton c) { return c == null ? "" : (String) swingAndWait(new F0() { public Object get() { try { return c.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getText();"; } }); } static String getText(final JTextComponent c) { return c == null ? "" : (String) swingAndWait(new F0() { public Object get() { try { return c.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getText();"; } }); } static String getText(final JLabel l) { return l == null ? "" : (String) swingAndWait(new F0() { public Object get() { try { return l.getText(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret l.getText();"; } }); } // returns the contents of text field for editable combo box static String getText(final JComboBox cb) { if (cb == null) return null; if (isEditableComboBox(cb)) return unnull((String) cb.getEditor().getItem()); else return str(cb.getSelectedItem()); } static String unidiff(String a, String b) { int contextSize = 1; return fromLines(BlockDiffer.generateUniDiff(toLines(a), toLines(b), contextSize)); } static String fixNewLines(String s) { int i = indexOf(s, '\r'); if (i < 0) return s; int l = s.length(); StringBuilder out = new StringBuilder(l); out.append(s, 0, i); for (; i < l; i++) { char c = s.charAt(i); if (c != '\r') out.append(c); else { out.append('\n'); if (i + 1 < l && s.charAt(i + 1) == '\n') ++i; } } return out.toString(); } static AutoCloseable tempInterceptPrintIfNotIntercepted(F1 f) { return print_byThread().get() == null ? tempInterceptPrint(f) : null; } // set this to relocate program's data static File programDir_mine; static File programDir() { return programDir(getProgramID()); } static File programDir(String snippetID) { boolean me = sameSnippetID(snippetID, programID()); if (programDir_mine != null && me) return programDir_mine; File dir = new File(javaxDataDir(), formatSnippetIDOpt(snippetID)); if (me) { String c = caseID(); if (nempty(c)) dir = newFile(dir, c); } return dir; } static File programDir(String snippetID, String subPath) { return new File(programDir(snippetID), subPath); } static int iteratorCount_int_close(Iterator i) { try { int n = 0; if (i != null) while (i.hasNext()) { i.next(); ++n; } if (i instanceof AutoCloseable) ((AutoCloseable) i).close(); return n; } catch (Exception __e) { throw rethrow(__e); } } static Object call(Object o) { return callF(o); } // varargs assignment fixer for a single string array argument static Object call(Object o, String method, String[] arg) { return call(o, method, new Object[] { arg }); } static Object call(Object o, String method, Object... args) { // ret call_cached(o, method, args); return call_withVarargs(o, method, args); } static String repeat(char c, int n) { n = Math.max(n, 0); char[] chars = new char[n]; for (int i = 0; i < n; i++) chars[i] = c; return new String(chars); } static List repeat(A a, int n) { n = Math.max(n, 0); List l = new ArrayList(n); for (int i = 0; i < n; i++) l.add(a); return l; } static List repeat(int n, A a) { return repeat(a, n); } static Object callOpt(Object o) { return callF(o); } static A callOpt(Object o, String method, Object... args) { return (A) callOpt_withVarargs(o, method, args); } static Object getOptMC(String field) { return getOpt(mc(), field); } static Map newWeakHashMap() { return _registerWeakMap(synchroMap(new WeakHashMap())); } // TODO: test if android complains about this static boolean isAWTThread() { if (isAndroid()) return false; if (isHeadless()) return false; return isAWTThread_awt(); } static boolean isAWTThread_awt() { return SwingUtilities.isEventDispatchThread(); } static void failIfUnlicensed() { assertTrue("license off", licensed()); } static Thread currentThread() { return Thread.currentThread(); } static boolean odd(int i) { return (i & 1) != 0; } static boolean odd(long i) { return (i & 1) != 0; } static boolean odd(BigInteger i) { return odd(toInt(i)); } static boolean endsWithLetterOrDigit(String s) { return s != null && s.length() > 0 && Character.isLetterOrDigit(s.charAt(s.length() - 1)); } // Use like this: renderVars(+x, +y) static String renderVars_str(Object... params) { List l = new ArrayList(); for (int i = 0; i + 1 < l(params); i += 2) l.add(params[i] + "=" + params[i + 1]); return trim(joinWithComma(l)); } static List newSubListOrSame(List l, int startIndex) { return newSubListOrSame(l, startIndex, l(l)); } static List newSubListOrSame(List l, int startIndex, int endIndex) { if (l == null) return null; int n = l(l); startIndex = max(0, startIndex); endIndex = min(n, endIndex); if (startIndex >= endIndex) return ll(); if (startIndex == 0 && endIndex == n) return l; return cloneList(l.subList(startIndex, endIndex)); } static CharSequence subCharSequence(CharSequence s, int x) { return subCharSequence(s, x, s == null ? 0 : s.length()); } static CharSequence subCharSequence(CharSequence s, int x, int y) { if (s == null) return null; if (x < 0) x = 0; if (x >= s.length()) return ""; if (y < x) y = x; if (y > s.length()) y = s.length(); return s.subSequence(x, y); } static int[] takeFirstOfIntArray(int[] b, int n) { return subIntArray(b, 0, n); } static int[] takeFirstOfIntArray(int n, int[] b) { return takeFirstOfIntArray(b, n); } static String getClassName(Object o) { return o == null ? "null" : o instanceof Class ? ((Class) o).getName() : o.getClass().getName(); } static String getType(Object o) { return getClassName(o); } static long getFileSize(String path) { return path == null ? 0 : new File(path).length(); } static long getFileSize(File f) { return f == null ? 0 : f.length(); } static List characters(final String s) { return stringAsCharacterList(s); } static RuntimeException asRuntimeException(Throwable t) { if (t instanceof Error) _handleError((Error) t); return t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t); } static List newSubList(List l, int startIndex, int endIndex) { return cloneList(subList(l, startIndex, endIndex)); } static List newSubList(List l, int startIndex) { return cloneList(subList(l, startIndex)); } static java.awt.Color awtColor(String hex) { byte[] b = bytesFromHex(dropPrefix("#", hex)); return new Color(ubyteToInt(b[0]), ubyteToInt(b[1]), ubyteToInt(b[2])); } static String codePointToString(int codePoint) { return new String(Character.toChars(codePoint)); } static String autoUnindent_mls(String s) { return autoUnindent(rtrim(dropLeadingNewLine(s))); } static int parseHexInt(String s) { return hexToInt(s); } static ReliableSingleThread rstWithDelay(final int delay, final Runnable r) { return new ReliableSingleThread(new Runnable() { public void run() { try { sleep(delay); callF(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "sleep(delay);\r\n callF(r);"; } }); } static ReliableSingleThread rstWithDelay(double seconds, Runnable r) { return rstWithDelay(toMS_int(seconds), r); } static String strUnnull(Object o) { return o == null ? "" : str(o); } static String jlabel_textAsHTML_center_ifNeeded(String text) { if (swic(text, "") && ewic(text, "")) return text; if (!containsNewLines(text)) return text; return jlabel_textAsHTML_center(text); } static boolean neq(Object a, Object b) { return !eq(a, b); } static void _handleError(Error e) { call(javax(), "_handleError", e); } static HashSet lithashset(A... items) { HashSet set = new HashSet(); for (A a : items) set.add(a); return set; } static void ping_okInCleanUp() { if (ping_pauseAll || ping_anyActions) ping_impl(true); } // this syntax should be removed... static Object getThreadLocal(Object o, String name) { ThreadLocal t = (ThreadLocal) (getOpt(o, name)); return t != null ? t.get() : null; } static A getThreadLocal(ThreadLocal tl) { return tl == null ? null : tl.get(); } static A getThreadLocal(ThreadLocal tl, A defaultValue) { return or(getThreadLocal(tl), defaultValue); } static ThreadLocal print_byThread_dontCreate() { return print_byThread; } static boolean isFalse(Object o) { return eq(false, o); } static String getStackTrace(Throwable throwable) { lastException(throwable); return getStackTrace_noRecord(throwable); } static String getStackTrace_noRecord(Throwable throwable) { StringWriter writer = new StringWriter(); throwable.printStackTrace(new PrintWriter(writer)); return hideCredentials(writer.toString()); } static String getStackTrace() { return getStackTrace_noRecord(new Throwable()); } static void print_append(Appendable buf, String s, int max) { try { synchronized (buf) { buf.append(s); if (buf instanceof StringBuffer) rotateStringBuffer(((StringBuffer) buf), max); else if (buf instanceof StringBuilder) rotateStringBuilder(((StringBuilder) buf), max); } } catch (Exception __e) { throw rethrow(__e); } } static void vmBus_send(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); pcallFAll(vm_busListeners_live(), msg, arg); pcallFAll(vm_busListenersByMessage_live().get(msg), msg, arg); } static void vmBus_send(String msg) { vmBus_send(msg, (Object) null); } static Map synchroMap() { return synchroHashMap(); } static Map synchroMap(Map map) { return new SynchronizedMap(map); } static List allPointsInRect(int w, int h) { return allPointsInRect(rect(w, h)); } static List allPointsInRect(Rect r) { int w = r.w, h = r.h; List l = emptyList(w * h); for (int y = 0; y < h; y++) for (int x = 0; x < w; x++) l.add(pt(r.x + x, r.y + y)); return l; } static BigInteger bigint(String s) { return new BigInteger(s); } static BigInteger bigint(long l) { return BigInteger.valueOf(l); } static void warnIfOddCount(Object... list) { if (odd(l(list))) printStackTrace("Odd list size: " + list); } static Object[] expandParams(Class c, Object[] params) { if (l(params) == 1) params = new Object[] { singleFieldName(c), params[0] }; else warnIfOddCount(params); return params; } // returns true if change static boolean _csetField(Concept c, String field, Object value) { try { Field f = setOpt_findField(c.getClass(), field); // print("cset: " + c.id + " " + field + " " + struct(value) + " " + f); if (value instanceof RC) value = c._concepts.getConcept((RC) value); value = deref(value); if (value instanceof String && l((String) value) >= concepts_internStringsLongerThan) value = intern((String) value); if (f == null) { // dynamic field (undeclared) assertIdentifier(field); Object oldVal = mapGet(c.fieldValues, field); if (value instanceof Concept) { if (oldVal instanceof Concept.Ref) // change existing reference return ((Concept.Ref) oldVal).set(((Concept) value)); else { // overwrite non-reference value if any, // create new reference dynamicObject_setRawFieldValue(c, field, c.new Ref(((Concept) value))); c.change(); return true; } } else { // value is not a concept // if it was a reference, cleanly delete it if (oldVal instanceof Concept.Ref) ((Concept.Ref) oldVal).unindexAndDrop(); if (eq(oldVal, value)) return false; if (isConceptList(value)) { // TODO: clean-up etc dynamicObject_setRawFieldValue(c, field, c.new RefL(((List) value))); c.change(); return true; } if (value == null) { // delete field dynamicObject_dropRawField(c, field); } else { // update or create field dynamicObject_setRawFieldValue(c, field, value); } c.change(); return true; } } else if (isSubtypeOf(f.getType(), Concept.Ref.class)) { // Concept.Ref magic ((Concept.Ref) f.get(c)).set((Concept) derefRef(value)); c.change(); return true; } else if (isSubtypeOf(f.getType(), Concept.RefL.class)) { // Concept.RefL magic ((Concept.RefL) f.get(c)).replaceWithList(lmap(__40 -> derefRef(__40), (List) value)); c.change(); return true; } else { Object old = f.get(c); if (neq(value, old)) { f.set(c, value); if (!isTransient(f)) c.change(); return true; } } return false; } catch (Exception __e) { throw rethrow(__e); } } static String unnull(String s) { return s == null ? "" : s; } static Collection unnull(Collection l) { return l == null ? emptyList() : l; } static List unnull(List l) { return l == null ? emptyList() : l; } static int[] unnull(int[] l) { return l == null ? emptyIntArray() : l; } static char[] unnull(char[] l) { return l == null ? emptyCharArray() : l; } static double[] unnull(double[] l) { return l == null ? emptyDoubleArray() : l; } static Map unnull(Map l) { return l == null ? emptyMap() : l; } static Iterable unnull(Iterable i) { return i == null ? emptyList() : i; } static A[] unnull(A[] a) { return a == null ? (A[]) emptyObjectArray() : a; } static BitSet unnull(BitSet b) { return b == null ? new BitSet() : b; } static Pt unnull(Pt p) { return p == null ? new Pt() : p; } // ifclass Symbol static Pair unnull(Pair p) { return p != null ? p : new Pair(null, null); } static long unnull(Long l) { return l == null ? 0L : l; } static A getVar(IF0 v) { return v == null ? null : v.get(); } static Object swingCall(final Object o, final String method, final Object... args) { return swing(new F0() { public Object get() { try { return call(o, method, args); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret call(o, method, args);"; } }); } static ThreadLocal imageGraphics_antiAlias = new ThreadLocal(); static Graphics2D imageGraphics(BufferedImage img) { return !isFalse(imageGraphics_antiAlias.get()) ? antiAliasGraphics(img) : createGraphics(img); } static ThreadLocal currentImage_var = new ThreadLocal(); static BufferedImage currentImage() { return currentImage_var.get(); } static void currentImage(BufferedImage img) { currentImage_var.set(img); } static String formatSnippetID(String id) { return "#" + parseSnippetID(id); } static String formatSnippetID(long id) { return "#" + id; } static Font loadFont(String snippetID) { try { return loadFont(snippetID, 12f); } catch (Exception __e) { throw rethrow(__e); } } static Font loadFont(InputStream in) { try { return Font.createFont(Font.TRUETYPE_FONT, in); } catch (Exception __e) { throw rethrow(__e); } } static Font loadFont(String snippetID, float fontSize) { return loadFont(loadLibrary(snippetID), fontSize); } static Font loadFont(File f, float fontSize) { try { return Font.createFont(Font.TRUETYPE_FONT, f).deriveFont(fontSize); } catch (Exception __e) { throw rethrow(__e); } } static Font loadFont(InputStream in, float fontSize) { try { return Font.createFont(Font.TRUETYPE_FONT, in).deriveFont(fontSize); } catch (Exception __e) { throw rethrow(__e); } } static double toDouble(Object o) { if (o instanceof Number) return ((Number) o).doubleValue(); if (o instanceof BigInteger) return ((BigInteger) o).doubleValue(); if (o instanceof String) return parseDouble(((String) o)); if (o == null) return 0.0; throw fail(o); } static Map createGraphics_modulators = synchroIdentityHashMap(); static Graphics2D createGraphics(BufferedImage img) { Graphics2D g = img.createGraphics(); Object mod = createGraphics_modulators.get(img); if (mod != null) callF(mod, g); return g; } // mod: voidfunc(Graphics2D) static void createGraphics_modulate(BufferedImage img, Object mod) { mapPut2(createGraphics_modulators, img, mod); } static double doubleRatio(double x, double y) { return y == 0 ? 0 : x / y; } static NavigableMap synchroTreeMap() { return Collections.synchronizedNavigableMap(new TreeMap()); } static boolean loadBufferedImage_useImageCache = true; static BufferedImage loadBufferedImage(String snippetIDOrURLOrFile) { try { ping(); if (snippetIDOrURLOrFile == null) return null; if (isURL(snippetIDOrURLOrFile)) return imageIO_readURL(snippetIDOrURLOrFile); if (isAbsolutePath(snippetIDOrURLOrFile)) return loadBufferedImage(new File(snippetIDOrURLOrFile)); if (!isSnippetID(snippetIDOrURLOrFile)) throw fail("Not a URL or snippet ID or file: " + snippetIDOrURLOrFile); String snippetID = "" + parseSnippetID(snippetIDOrURLOrFile); IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return loadBufferedImage(rl.loadLibrary(snippetID)); File dir = imageSnippetsCacheDir(); if (loadBufferedImage_useImageCache) { dir.mkdirs(); File file = new File(dir, snippetID + ".png"); if (file.exists() && file.length() != 0) try { return ImageIO.read(file); } catch (Throwable e) { e.printStackTrace(); // fall back to loading from sourceforge } } String imageURL = snippetImageURL_http(snippetID); print("Loading image: " + imageURL); BufferedImage image = imageIO_readURL(imageURL); if (loadBufferedImage_useImageCache) { File tempFile = new File(dir, snippetID + ".tmp." + System.currentTimeMillis()); ImageIO.write(image, "png", tempFile); tempFile.renameTo(new File(dir, snippetID + ".png")); // Log.info("Cached image."); } // Log.info("Loaded image."); return image; } catch (Exception __e) { throw rethrow(__e); } } static BufferedImage loadBufferedImage(File file) { try { return file.isFile() ? ImageIO.read(file) : null; } catch (Exception __e) { throw rethrow(__e); } } static Rect pointsRect(int x1, int y1, int x2, int y2) { return new Rect(x1, y1, x2 - x1, y2 - y1); } static Pt centerTextInRect(FontMetrics fm, String s, Rect r) { int tw = fm.stringWidth(s), th = fm.getHeight(); return pt(r.x + (r.w - tw) / 2, r.y + (r.h - th) / 2 + fm.getAscent()); } static A focus(final A a) { if (a != null) swingLater(new Runnable() { public void run() { try { a.requestFocus(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.requestFocus();"; } }); return a; } // get purpose 1: access a list/array/map (safer version of x.get(y)) static A get(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } // seems to conflict with other signatures /*static B get(Map map, A key) { ret map != null ? map.get(key) : null; }*/ static A get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } // default to false static boolean get(boolean[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : false; } // get purpose 2: access a field by reflection or a map static Object get(Object o, String field) { try { if (o == null) return null; if (o instanceof Class) return get((Class) o, field); if (o instanceof Map) return ((Map) o).get(field); Field f = getOpt_findField(o.getClass(), field); if (f != null) { makeAccessible(f); return f.get(o); } if (o instanceof DynamicObject) return ((DynamicObject) o).fieldValues.get(field); } catch (Exception e) { throw asRuntimeException(e); } throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName()); } static Object get_raw(String field, Object o) { return get_raw(o, field); } static Object get_raw(Object o, String field) { try { if (o == null) return null; Field f = get_findField(o.getClass(), field); makeAccessible(f); return f.get(o); } catch (Exception __e) { throw rethrow(__e); } } static Object get(Class c, String field) { try { Field f = get_findStaticField(c, field); makeAccessible(f); return f.get(null); } catch (Exception e) { throw new RuntimeException(e); } } static Field get_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static Field get_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } static Object get(String field, Object o) { return get(o, field); } static boolean get(BitSet bs, int idx) { return bs != null && bs.get(idx); } static ArrayList emptyList() { return new ArrayList(); // ret Collections.emptyList(); } static ArrayList emptyList(int capacity) { return new ArrayList(max(0, capacity)); } // Try to match capacity static ArrayList emptyList(Iterable l) { return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList(); } static ArrayList emptyList(Object[] l) { return emptyList(l(l)); } // get correct type at once static ArrayList emptyList(Class c) { return new ArrayList(); } // unclear semantics as to whether return null on null static ArrayList asList(A[] a) { return a == null ? new ArrayList() : new ArrayList(Arrays.asList(a)); } static ArrayList asList(int[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (int i : a) l.add(i); return l; } static ArrayList asList(long[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (long i : a) l.add(i); return l; } static ArrayList asList(float[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (float i : a) l.add(i); return l; } static ArrayList asList(double[] a) { if (a == null) return null; ArrayList l = emptyList(a.length); for (double i : a) l.add(i); return l; } static ArrayList asList(Iterable s) { if (s instanceof ArrayList) return (ArrayList) s; ArrayList l = new ArrayList(); if (s != null) for (A a : s) l.add(a); return l; } static ArrayList asList(Producer p) { ArrayList l = new ArrayList(); A a; if (p != null) while ((a = p.next()) != null) l.add(a); return l; } static ArrayList asList(Enumeration e) { ArrayList l = new ArrayList(); if (e != null) while (e.hasMoreElements()) l.add(e.nextElement()); return l; } static List intRangeList(int b) { return intRangeList(0, b); } static List intRangeList(final int a, final int b) { final int l = max(0, b - a); return new RandomAccessAbstractList() { public int size() { return l; } public Integer get(int i) { return i >= 0 && i < l ? a + i : null; } }; } static JPanel smartAdd(JPanel panel, List parts) { for (Object o : parts) addToContainer(panel, wrapForSmartAdd(o)); return panel; } static JPanel smartAdd(JPanel panel, Object... parts) { return smartAdd(panel, asList(parts)); } static int identityHashCode(Object o) { return System.identityHashCode(o); } static Class _getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { // could optimize this return null; } } static Class _getClass(Object o) { return o == null ? null : o instanceof Class ? (Class) o : o.getClass(); } static Class _getClass(Object realm, String name) { try { return getClass(realm).getClassLoader().loadClass(classNameToVM(name)); } catch (ClassNotFoundException e) { // could optimize this return null; } } static boolean isMain() { return isMainProgram(); } static boolean vmHasResourceLoader() { return vm_getResourceLoader() != null; } static void preloadProgramTitle() { { startThread(new Runnable() { public void run() { try { programTitle(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "programTitle();"; } }); } } static void stopTimer(java.util.Timer timer) { if (timer != null) timer.cancel(); } static java.util.Timer doLater_daemon(long delay, final Object r) { final java.util.Timer timer = new java.util.Timer(true); timer.schedule(timerTask(r, timer), delay); return timer; } static java.util.Timer doLater_daemon(double delaySeconds, final Object r) { return doLater_daemon(toMS(delaySeconds), r); } static long toMS(double seconds) { return (long) (seconds * 1000); } static int serverAutoRestartMD5_timeout = 10000; static String serverAutoRestartMD5(String programID) { return loadPageSilentlyWithTimeout("http://botcompany.de/1010693/raw?id=" + psI(programID), serverAutoRestartMD5_timeout); } static String serverAutoRestartMD5() { return serverAutoRestartMD5(programID()); } static String programID() { return getProgramID(); } static String programID(Object o) { return getProgramID(o); } static boolean isMD5(String s) { return l(s) == 32 && isLowerHexString(s); } static String md5(String text) { try { if (text == null) return "-"; // maybe different than the way PHP does it... return bytesToHex(md5_impl(toUtf8(text))); } catch (Exception __e) { throw rethrow(__e); } } static String md5(byte[] data) { if (data == null) return "-"; return bytesToHex(md5_impl(data)); } static byte[] md5_impl(byte[] data) { try { return MessageDigest.getInstance("MD5").digest(data); } catch (Exception __e) { throw rethrow(__e); } } static String md5(File file) { return md5OfFile(file); } static String loadCachedTranspilation(String id) { try { return loadTextFilePossiblyGZipped(getCachedTranspilationFile(id)); } catch (Throwable __e) { return null; } } static String autoRestart_localMD5; static String autoRestart_localMD5() { if (autoRestart_localMD5 == null) autoRestart_localMD5 = md5(loadCachedTranspilation(programID())); return autoRestart_localMD5; } static String programTitle() { return getProgramName(); } static void restartWithDelay(int delay) { Object j = getJavaX(); call(j, "preKill"); call(j, "nohupJavax", smartJoin((String[]) get(j, "fullArgs")), call(j, "fullVMArguments")); sleep(delay); System.exit(0); sleep(); } static volatile boolean sleep_noSleep = false; static void sleep(long ms) { ping(); if (ms < 0) return; // allow spin locks if (isAWTThread() && ms > 100) throw fail("Should not sleep on AWT thread"); try { Thread.sleep(ms); } catch (Exception e) { throw new RuntimeException(e); } } static void sleep() { try { if (sleep_noSleep) throw fail("nosleep"); print("Sleeping."); sleepQuietly(); } catch (Exception __e) { throw rethrow(__e); } } static boolean logModuleOutput_installed = false; static void logModuleOutput() { if (logModuleOutput_installed) return; logModuleOutput_installed = true; final File logFile = getProgramFile("output.txt"); final LineBuffer buf = new LineBuffer(new VF1() { public void get(String line) { try { appendToTextFile(logFile, "[" + localDateWithMilliseconds() + "] " + line + "\n"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "appendToTextFile(logFile, \"[\" + localDateWithMilliseconds() + \"] \" + line + \"..."; } }); print_forAllThreads(new VF1() { public void get(String s) { try { buf.append(s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "buf.append(s);"; } }); } static JFrame consoleFrame() { return (JFrame) getOpt(get(getJavaX(), "console"), "frame"); } static void autoVMExit() { call(getJavaX(), "autoVMExit"); } static void swingLater(long delay, final Object r) { javax.swing.Timer timer = new javax.swing.Timer(toInt(delay), actionListener(wrapAsActivity(r))); timer.setRepeats(false); timer.start(); } static void swingLater(Object r) { SwingUtilities.invokeLater(toRunnable(r)); } static boolean headless() { return isHeadless(); } static void consoleFont(Font font) { callOpt(getConsoleTextArea_gen(), "setFont", font); } static void setConsoleHeight(int h) { setFrameHeight(consoleFrame(), h); } static void centerBigConsole() { if (headless()) return; // substance(); { swing(new Runnable() { public void run() { try { setConsoleInputFontSize(20); consoleInputField().setHorizontalAlignment(JTextField.CENTER); centerConsoleFrame(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "setConsoleInputFontSize(20);\r\n consoleInputField().setHorizontalAlignment(..."; } }); } } static void renameConsole(String title) { setConsoleTitle(title); } static void consoleMargin(int margin) { call(getConsoleTextArea_gen(), "setBorder", BorderFactory.createEmptyBorder(margin, margin, margin, margin)); } static void clearConsole() { if (!isAWTThread()) // SHOULD clear the system.out buffer sleep(111); try { swingAndWait(new Runnable() { public void run() { try { Object console = getOpt(javax(), "console"); if (console != null) { call(getFirstNonNullField(console, "textArea", "logView"), "setText", ""); set(console, "buf", new StringBuffer()); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Object console = getOpt(javax(), \"console\");\r\n if (console != null) {\r\n ..."; } }); } catch (Throwable __e) { _handleException(__e); } } static void focusConsole(String s) { setConsoleInput(s); focusConsole(); } static void focusConsole() { JComponent tf = consoleInputFieldOrComboBox(); if (tf != null) { // print("Focusing console"); tf.requestFocus(); } } volatile static boolean conceptsAndBot_running = false; static boolean conceptsAndBot_thinOnStart = true; static void conceptsAndBot() { conceptsAndBot(null); } static void conceptsAndBot(Integer autoSaveInterval) { if (conceptsAndBot_running) return; conceptsAndBot_running = true; Concepts cc = db_mainConcepts(); try { if (cc.useFileLock) { if (!cc.fileLock().tryToLock()) { ensureDBNotRunning(dbBotStandardName()); cc.fileLock().forceLock(); } } else ensureDBNotRunning(dbBotStandardName()); } catch (Throwable _e) { // SAFETY cc.dontSave = true; throw rethrow(_e); } cc.persist(autoSaveInterval); dbBot(false); if (conceptsAndBot_thinOnStart) { try { thinAProgramsBackups(getDBProgramID(), true); } catch (Throwable __e) { _handleException(__e); } } } static A uniqueConcept(Class c, Object... params) { return uniqueConcept(db_mainConcepts(), c, params); } static A uniqueConcept(Concepts cc, Class c, Object... params) { AutoCloseable __1 = tempDBLock(cc); try { params = expandParams(c, params); A x = findConceptWhere(cc, c, params); if (x == null) { x = unlisted(c); csetAll(x, params); cc.register(x); } return x; } finally { _close(__1); } } // TODO: if field is a Ref<>, you can thoretically use findBackRefs static A findConceptWhere(Class c, Object... params) { return findConceptWhere(db_mainConcepts(), c, params); } static A findConceptWhere(Concepts concepts, Class c, Object... params) { ping(); params = expandParams(c, params); // indexed if (concepts.fieldIndices != null) for (int i = 0; i < l(params); i += 2) { IFieldIndex index = concepts.getFieldIndex(c, (String) params[i]); if (index != null) { for (A x : index.getAll(params[i + 1])) if (checkConceptFields(x, params)) return x; return null; } } // table scan for (A x : concepts.list(c)) if (checkConceptFields(x, params)) return x; return null; } static Concept findConceptWhere(Concepts concepts, String c, Object... params) { for (Concept x : concepts.list(c)) if (checkConceptFields(x, params)) return x; return null; } static void fixContextClassLoader() { Thread.currentThread().setContextClassLoader(myClassLoader()); } static File loadBinarySnippet(String snippetID) { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); return loadBinarySnippet_noResourceLoader(snippetID); } static File loadBinarySnippet_noResourceLoader(String snippetID) { try { long id = parseSnippetID(snippetID); if (isImageServerSnippet(id)) return loadImageAsFile(snippetID); File f = DiskSnippetCache_getLibrary(id); if (fileSize(f) == 0) f = loadDataSnippetToFile_noResourceLoader(snippetID); return f; } catch (Exception __e) { throw rethrow(__e); } } static void setDefaultFrameIcon(String icon) { setOptMC("makeFrame_defaultIcon", icon); } static String makeFrame_defaultIcon; static boolean makeFrame_hideConsole = false; static ThreadLocal> makeFrame_post = new ThreadLocal(); static JFrame makeFrame() { return makeFrame((Component) null); } static JFrame makeFrame(Object content) { return makeFrame(programTitle(), content); } static JFrame makeFrame(String title) { return makeFrame(title, null); } static JFrame makeFrame(String title, Object content) { return makeFrame(title, content, true); } static JFrame makeFrame(final String title, final Object content, final boolean showIt) { final VF1 post = optParam(makeFrame_post); return swing(new F0() { public JFrame get() { try { if (getFrame(content) != null) return getFrame(setFrameTitle((Component) content, title)); final JFrame frame = new JFrame(title); if (makeFrame_defaultIcon != null) setFrameIconLater(frame, makeFrame_defaultIcon); _initFrame(frame); Component wrapped = wrap(content); if (wrapped != null) frame.getContentPane().add(wrapped); frame.setBounds(defaultNewFrameBounds()); callF(post, frame); if (showIt) frame.setVisible(true); // callOpt(content, "requestFocus"); // exitOnFrameClose(frame); if (showIt && makeFrame_hideConsole) { hideConsole(); makeFrame_hideConsole = false; } return frame; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (getFrame(content) != null)\r\n ret getFrame(setFrameTitle((Component) ..."; } }); } static boolean frameTooSmall(JFrame frame) { return frame.getWidth() < 100 || frame.getHeight() < 50; } static void frameStandardSize(JFrame frame) { frame.setBounds(300, 100, 500, 400); } static class tempRememberListener_c implements IFieldsToList { static final String _fieldOrder = "mainObject removeMethod listener"; Object mainObject; String removeMethod; Object listener; tempRememberListener_c() { } tempRememberListener_c(Object mainObject, String removeMethod, Object listener) { this.listener = listener; this.removeMethod = removeMethod; this.mainObject = mainObject; } public String toString() { return shortClassName(this) + "(" + mainObject + ", " + removeMethod + ", " + listener + ")"; } public boolean equals(Object o) { if (!(o instanceof tempRememberListener_c)) return false; tempRememberListener_c __1 = (tempRememberListener_c) o; return eq(mainObject, __1.mainObject) && eq(removeMethod, __1.removeMethod) && eq(listener, __1.listener); } public int hashCode() { int h = 1262836985; h = boostHashCombine(h, _hashCode(mainObject)); h = boostHashCombine(h, _hashCode(removeMethod)); h = boostHashCombine(h, _hashCode(listener)); return h; } public Object[] _fieldsToList() { return new Object[] { mainObject, removeMethod, listener }; } } static AutoCloseable tempRememberListener(Object mainObject, String removeMethod, Object listener) { return tempHoldInstance(new tempRememberListener_c(mainObject, removeMethod, listener)); } static Object pcallF(Object f, Object... args) { return pcallFunction(f, args); } static A pcallF(F0 f) { try { return f == null ? null : f.get(); } catch (Throwable __e) { return null; } } static B pcallF(F1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { return null; } } static void pcallF(VF1 f, A a) { try { { if (f != null) f.get(a); } } catch (Throwable __e) { _handleException(__e); } } static B pcallF(IF1 f, A a) { try { return f == null ? null : f.get(a); } catch (Throwable __e) { return null; } } static Thread startThread(Object runnable) { return startThread(defaultThreadName(), runnable); } static Thread startThread(String name, Object runnable) { runnable = wrapAsActivity(runnable); return startThread(newThread(toRunnable(runnable), name)); } static Thread startThread(Thread t) { _registerThread(t); t.start(); return t; } static void close_pcall(AutoCloseable c) { if (c != null) { try { c.close(); } catch (Throwable __e) { _handleException(__e); } } } static Collection values(Map map) { return map == null ? emptyList() : map.values(); } // convenience shortcut for values_gen static Collection values(Object map) { return values((Map) map); } static void preCleanUp(Object c) { if (c instanceof Collection) { for (Object o : ((Collection) c)) preCleanUp(o); return; } callOpt(c, "licensed_off"); // so ping notices setOpt(c, "ping_anyActions", true); setOpt(c, "cleaningUp_flag", true); } static Field setOpt_findField(Class c, String field) { HashMap map; synchronized (getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } return map.get(field); } static void setOpt(Object o, String field, Object value) { try { if (o == null) return; Class c = o.getClass(); HashMap map; if (getOpt_cache == null) // in class init map = getOpt_makeCache(c); else synchronized (getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } if (map == getOpt_special) { if (o instanceof Class) { setOpt((Class) o, field, value); return; } // It's probably a subclass of Map. Use raw method setOpt_raw(o, field, value); return; } Field f = map.get(field); if (f != null) // possible improvement: skip setAccessible { smartSet(f, o, value); return; } if (o instanceof DynamicObject) setDyn(((DynamicObject) o), field, value); } catch (Exception __e) { throw rethrow(__e); } } static void setOpt(Class c, String field, Object value) { if (c == null) return; try { // TODO: optimize Field f = setOpt_findStaticField(c, field); if (f != null) smartSet(f, null, value); } catch (Exception e) { throw new RuntimeException(e); } } static Field setOpt_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) { makeAccessible(f); return f; } _c = _c.getSuperclass(); } while (_c != null); return null; } static void innerCleanUp(Object c) { // call custom cleanMeUp() and cleanMeUp_*() functions if (!isFalse(pcallOpt(c, "cleanMeUp"))) for (String name : sorted(methodsStartingWith(c, "cleanMeUp_"))) try { callOpt(c, name); } catch (Throwable e) { print("Error cleaning up: " + programID(c)); _handleException(e); } } static void innerCleanUp() { innerCleanUp(mc()); } static Object getOpt(Object o, String field) { return getOpt_cached(o, field); } static Object getOpt(String field, Object o) { return getOpt_cached(o, field); } static Object getOpt_raw(Object o, String field) { try { Field f = getOpt_findField(o.getClass(), field); if (f == null) return null; makeAccessible(f); return f.get(o); } catch (Exception __e) { throw rethrow(__e); } } // access of static fields is not yet optimized static Object getOpt(Class c, String field) { try { if (c == null) return null; Field f = getOpt_findStaticField(c, field); if (f == null) return null; makeAccessible(f); return f.get(null); } catch (Exception __e) { throw rethrow(__e); } } static Field getOpt_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static Object pcallOpt(Object o, String method, Object... args) { try { return callOpt(o, method, args); } catch (Throwable __e) { _handleException(__e); } return null; } static volatile PersistableThrowable _handleException_lastException; static List _handleException_onException = synchroList(ll("printStackTrace2")); static boolean _handleException_showThreadCancellations = false; static void _handleException(Throwable e) { _handleException_lastException = persistableThrowable(e); Throwable e2 = innerException(e); if (e2.getClass() == RuntimeException.class && eq(e2.getMessage(), "Thread cancelled.") || e2 instanceof InterruptedException) { if (_handleException_showThreadCancellations) System.out.println(getStackTrace_noRecord(e2)); return; } for (Object f : cloneList(_handleException_onException)) try { callF(f, e); } catch (Throwable e3) { try { // not using pcall here - it could lead to endless loops printStackTrace2(e3); } catch (Throwable e4) { System.out.println(getStackTrace(e3)); System.out.println(getStackTrace(e4)); } } } static List registeredThreads(Object o) { Map map = (Map) (getOpt(o, "_registerThread_threads")); if (map == null) return ll(); // force clean-up map.size(); synchronized (map) { return asList(keys(map)); } } static List registeredThreads() { // force clean-up _registerThread_threads.size(); return asList(keys(_registerThread_threads)); } static boolean nempty(Collection c) { return !empty(c); } static boolean nempty(CharSequence s) { return !empty(s); } static boolean nempty(Object[] o) { return !empty(o); } static boolean nempty(byte[] o) { return !empty(o); } static boolean nempty(int[] o) { return !empty(o); } static boolean nempty(Map m) { return !empty(m); } static boolean nempty(Iterator i) { return i != null && i.hasNext(); } static boolean nempty(Object o) { return !empty(o); } static String n2(long l) { return formatWithThousands(l); } static String n2(Collection l) { return n2(l(l)); } static String n2(Map map) { return n2(l(map)); } static String n2(double l, String singular) { return n2(l, singular, singular + "s"); } static String n2(double l, String singular, String plural) { if (fraction(l) == 0) return n2((long) l, singular, plural); else return l + " " + plural; } static String n2(long l, String singular, String plural) { return n_fancy2(l, singular, plural); } static String n2(long l, String singular) { return n_fancy2(l, singular, singular + "s"); } static String n2(Collection l, String singular) { return n2(l(l), singular); } static String n2(Collection l, String singular, String plural) { return n_fancy2(l, singular, plural); } static String n2(Map m, String singular, String plural) { return n_fancy2(m, singular, plural); } static String n2(Map m, String singular) { return n2(l(m), singular); } static String n2(Object[] a, String singular) { return n2(l(a), singular); } static String n2(Object[] a, String singular, String plural) { return n_fancy2(a, singular, plural); } static String n2(MultiSet ms, String singular, String plural) { return n_fancy2(ms, singular, plural); } static String joinWithComma(Collection c) { return join(", ", c); } static String joinWithComma(String... c) { return join(", ", c); } static String joinWithComma(Pair p) { return p == null ? "" : joinWithComma(str(p.a), str(p.b)); } static List allToString(Iterable c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static List allToString(Object[] c) { List l = new ArrayList(); for (Object o : unnull(c)) l.add(str(o)); return l; } static void interruptThreads(Collection threads) { for (Thread t : unnull(threads)) interruptThread(t); } static void interruptThreads(Class mainClass) { interruptThreads(registeredThreads(mainClass)); } static void retireClassLoader(ClassLoader cl) { if (isJavaXClassLoader(cl)) setOptAll(cl, "retired", true, "retiredMarker", new DefunctClassLoader()); } static void assertNotOnAWTThread() { assertFalse("Can't do this in AWT thread", isAWTThread()); } static Class __javax; static Class getJavaX() { try { return __javax; } catch (Exception __e) { throw rethrow(__e); } } static JTextArea jTextArea_noUndo() { return jTextArea_noUndo(""); } static JTextArea jTextArea_noUndo(final String text) { return swingNu(JTextArea.class, text); } static void swingAndWait(Runnable r) { try { if (isAWTThread()) r.run(); else EventQueue.invokeAndWait(addThreadInfoToRunnable(r)); } catch (Exception __e) { throw rethrow(__e); } } static Object swingAndWait(final Object f) { if (isAWTThread()) return callF(f); else { final Var result = new Var(); swingAndWait(new Runnable() { public void run() { try { result.set(callF(f)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "result.set(callF(f));"; } }); return result.get(); } } static AbstractAction abstractAction(String name, final Object runnable) { return new AbstractAction(name) { public void actionPerformed(ActionEvent evt) { pcallF(runnable); } }; } static RootPaneContainer getPossiblyInternalFrame(Component c) { JInternalFrame f = getInternalFrame(c); if (f != null) return f; return optCast(RootPaneContainer.class, getWindow(c)); } static JMenuBar addMenuBar(final Component c) { return swing(new F0() { public JMenuBar get() { try { RootPaneContainer f = getPossiblyInternalFrame(c); if (f == null) return null; JMenuBar bar = (JMenuBar) (call(f, "getJMenuBar")); if (bar == null) { setMenuBar(f, bar = new JMenuBar()); revalidate((Component) f); } return bar; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "RootPaneContainer f = getPossiblyInternalFrame(c);\r\n if (f == null) null;\r..."; } }); } static Pair jmenu_autoMnemonic(String s) { int i = indexOf(s, '&'); if (i >= 0 && i < l(s) && isLetterOrDigit(s.charAt(i + 1))) return pair(substring(s, 0, i) + substring(s, i + 1), (int) s.charAt(i + 1)); return pair(s, 0); } static JMenu getMenuNamed(JMenuBar bar, String name) { int n = bar.getMenuCount(); for (int i = 0; i < n; i++) { JMenu m = bar.getMenu(i); if (m != null && eq(m.getText(), name)) return m; } return null; } static void fillJMenu(final JMenu m, Object... x) { // ifdef fillJMenu_debug // print("fillJMenu " + m); // endifdef if (x == null) return; for (int i = 0; i < l(x); i++) { Object o = x[i], y = get(x, i + 1); if (o instanceof List) fillJMenu(m, asArray((List) o)); else if (isMenuSeparatorIndicator(o)) { if (// auto-skip separator if at top menuItemCount(m) != 0) m.addSeparator(); } else if (o instanceof LiveValue && ((LiveValue) o).getType() == String.class && isRunnableX(y)) { final LiveValue lv = (LiveValue) o; final JMenuItem mi = jmenuItem(or2(unCurlyBracket(lv.get()), "..."), y); bindLiveValueListenerToComponent(mi, lv, new Runnable() { public void run() { try { String s = lv.get(); if (isCurlyBracketed(s)) { setEnabled(mi, false); s = unCurlyBracket(s); } else setEnabled(mi, true); setText(mi, s); revalidate(m); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String s = lv.get();\r\n if (isCurlyBracketed(s)) {\r\n setEnable..."; } }); print("bound live value " + lv + " to menu item " + mi); m.add(mi); ++i; } else if (o instanceof String && isRunnableX(y)) { m.add(jmenuItem((String) o, y)); ++i; } else if (o instanceof JMenuItem) // "call" might use wrong method m.add((JMenuItem) o); else if (o instanceof String || o instanceof Action || o instanceof Component) call(m, "add", o); else if (o == null && y instanceof Runnable) // text == null => disabled item ++i; else if (o != null) print("Unknown menu item: " + o); } } static int menuItemCount(JMenu menu) { return menu == null ? 0 : swing(() -> menu.getItemCount()); } static A revalidate(final A c) { if (c == null || !c.isShowing()) return c; { swing(new Runnable() { public void run() { try { // magic combo to actually relayout and repaint c.revalidate(); c.repaint(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "// magic combo to actually relayout and repaint\r\n c.revalidate();\r\n c.r..."; } }); } return c; } static void revalidate(JFrame f) { revalidate((Component) f); } static void revalidate(JInternalFrame f) { revalidate((Component) f); } static JMenu jmenu(final String title, final Object... items) { return swing(new F0() { public JMenu get() { try { JMenu menu = new JMenu(title); fillJMenu(menu, items); return menu; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JMenu menu = new(title);\r\n fillJMenu(menu, items);\r\n ret menu;"; } }); } static void showConsole() { callOpt(get(javax(), "console"), "showConsole"); } static boolean activateFrame(final Component c, Object... __) { return swing(new F0() { public Boolean get() { try { Frame f = getAWTFrame(c); if (f == null) return false; if (!f.isVisible()) f.setVisible(true); boolean windowsHack = optPar("windowsHack", __, true); boolean iconified = f.getState() == Frame.ICONIFIED; boolean maximize = boolPar("maximize", __); if (iconified) f.setState(maximize ? Frame.MAXIMIZED_BOTH : Frame.NORMAL); // My glorious Windows hack // See: https://stackoverflow.com/questions/309023/how-to-bring-a-window-to-the-front if (windowsHack && !iconified && isWindows()) { boolean fullscreen = f.getExtendedState() == Frame.MAXIMIZED_BOTH; f.setExtendedState(JFrame.ICONIFIED); f.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL); } f.toFront(); return true; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Frame f = getAWTFrame(c);\r\n if (f == null) false;\r\n if (!f.isVisible())..."; } }); } static boolean jmenuItem_newThreads = false; static JMenuItem jmenuItem(final String text) { return jMenuItem(text, null); } static JMenuItem jmenuItem(final String text, final Object r) { return swing(new F0() { public JMenuItem get() { try { Pair p = jmenu_autoMnemonic(dropPrefix("[disabled] ", text)); JMenuItem mi = new JMenuItem(p.a); if (startsWith(text, "[disabled] ")) disableMenuItem(mi); if (p.b != 0) mi.setMnemonic(p.b); mi.addActionListener(jmenuItem_newThreads ? actionListenerInNewThread(r) : actionListener(r)); return mi; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Pair p = jmenu_autoMnemonic(dropPrefix(\"[disabled] \", text));\r\n JM..."; } }); } static MenuItem menuItem(String text, final Object r) { MenuItem mi = new MenuItem(text); mi.addActionListener(actionListener(r)); return mi; } static void addDirectMenuItem(JMenuBar mb, String text, Object action) { if (mb != null) { swing(new Runnable() { public void run() { try { addDirectMenuItem(mb, directJMenuItem(text, action)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addDirectMenuItem(mb, directJMenuItem(text, action));"; } }); } } static void addDirectMenuItem(Component c, String text, Object action) { addDirectMenuItem(addMenuBar(c), text, action); } static void addDirectMenuItem(JMenuBar mb, JMenuItem menuItem) { if (mb != null) { swing(new Runnable() { public void run() { try { mb.add(menuItem); revalidate(mb); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mb.add(menuItem);\r\n revalidate(mb);"; } }); } } static A jMaxWidth(int w, A c) { Dimension size = c.getMaximumSize(); c.setMaximumSize(new Dimension(w, size.height)); // this helps return jPreferWidth(w, c); } static A jMaxWidth(A c, int w) { return jMaxWidth(w, c); } static int preferredWidth(Component c) { return c == null ? 0 : getPreferredSize(c).width; } static void addAndValidate(final Container c, final Component x) { if (c != null && x != null) { swing(new Runnable() { public void run() { try { c.add(x); c.revalidate(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.add(x);\r\n c.revalidate();"; } }); } } static ChangeListener changeListener(final Object r) { return new ChangeListener() { public void stateChanged(ChangeEvent e) { pcallF(r); } }; } static ItemListener itemListener(final Object r) { return new ItemListener() { public void itemStateChanged(ItemEvent e) { pcallF(r); } }; } // action = runnable or method name static void onUpdate(JComponent c, final Object r) { if (c instanceof JTextComponent) ((JTextComponent) c).getDocument().addDocumentListener(new DocumentListener() { public void insertUpdate(DocumentEvent e) { call(r); } public void removeUpdate(DocumentEvent e) { call(r); } public void changedUpdate(DocumentEvent e) { call(r); } }); else if (// JCheckBox and others c instanceof ItemSelectable) ((ItemSelectable) c).addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { call(r); } }); else print("Warning: onUpdate doesn't know " + getClassName(c)); } static void onUpdate(List l, Object r) { for (JComponent c : l) onUpdate(c, r); } static boolean isEditableComboBox(final JComboBox cb) { return cb != null && swing(new F0() { public Boolean get() { try { return cb.isEditable(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret cb.isEditable();"; } }); } static JTextField textFieldFromComboBox(JComboBox cb) { return (JTextField) cb.getEditor().getEditorComponent(); } static JComboBox onSelectedItem(final JComboBox cb, final VF1 f) { addActionListener(cb, new Runnable() { public void run() { try { pcallF(f, selectedItem(cb)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(f, selectedItem(cb))"; } }); return cb; } static int toInt(Object o) { if (o == null) return 0; if (o instanceof Number) return ((Number) o).intValue(); if (o instanceof String) return parseInt(((String) o)); if (o instanceof Boolean) return boolToInt(((Boolean) o)); throw fail("woot not int: " + getClassName(o)); } static int toInt(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static JPanel westAndCenter(final Component w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.WEST, wrap(w)); panel.add(BorderLayout.CENTER, wrap(c)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.WEST..."; } }); } static int withRightMargin_defaultWidth = 6; static JPanel withRightMargin(Component c) { return withRightMargin(withRightMargin_defaultWidth, c); } static JPanel withRightMargin(final int w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, w)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } // c = Component or something implementing swing() static JComponent wrap(Object swingable) { return _recordNewSwingComponent(wrap_2(swingable)); } static JComponent wrap_2(Object swingable) { if (swingable == null) return null; JComponent c; if (swingable instanceof Component) c = componentToJComponent(((Component) swingable)); else if (swingable instanceof Swingable) c = componentToJComponent(((Swingable) swingable).visualize()); else c = componentToJComponent((Component) callOpt(swingable, "swing")); if (c instanceof JTable || c instanceof JList || c instanceof JTextArea || c instanceof JEditorPane || c instanceof JTextPane || c instanceof JTree) return jscroll(c); return c == null ? jlabel(str(swingable)) : c; } static boolean newButton_autoToolTip = true; // action can be Runnable or a function name static JButton newButton(final String text, final Object action) { return swing(new F0() { public JButton get() { try { String text2 = dropPrefix("[disabled] ", text); final JButton btn = new JButton(text2); if (l(text2) < l(text)) btn.setEnabled(false); if (newButton_autoToolTip) { btn.setToolTipText(btn.getText()); // onChangeAndNow(btn, r { btn.setToolTipText(btn.getText()) }); } // submitButtonOnEnter(btn); // test this first if (action != null) btn.addActionListener(actionListener(action, btn)); return btn; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "S text2 = dropPrefix(\"[disabled] \", text);\r\n final JButton btn = new JButt..."; } }); } static A swingNu(final Class c, final Object... args) { return swingConstruct(c, args); } static JTextField jTextField() { return jTextField(""); } static JTextField jTextField(final String text) { return swing(new F0() { public JTextField get() { try { JTextField tf = new JTextField(unnull(text)); standardTextFieldPopupMenu(tf); jenableUndoRedo(tf); tf.selectAll(); return tf; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JTextField tf = new JTextField(unnull(text));\r\n standardTextFieldPopupMenu..."; } }); } static JTextField jTextField(Object o) { return jTextField(strOrEmpty(o)); } static Class getFieldType(Object o, String field) { return fieldType(o, field); } // magic cast static A cget(Object c, String field) { Object o = getOpt(c, field); if (o instanceof Concept.Ref) return (A) ((Concept.Ref) o).get(); return (A) o; } static A cget(String field, Object c) { return cget(c, field); } static void onConceptChangeByClass_notOnAllChanged(Class type, Runnable r) { onConceptChangeByClass_notOnAllChanged(db_mainConcepts(), type, r); } static void onConceptChangeByClass_notOnAllChanged(Concepts cc, Class type, Runnable r) { cc.addConceptIndex(new IConceptIndex() { public void update(Concept c) { if (instanceOf(c, type)) pcallF(r); } public void remove(Concept c) { if (instanceOf(c, type)) pcallF(r); } }); } static JLabel jcenteredLabel(String text) { return setHorizontalAlignment(JLabel.CENTER, jLabel(text)); } static JLabel jcenteredLabel() { return jcenteredLabel(" "); } static JPanel vgridWithSpacing(Object... _parts) { return swing(() -> { int spacing = 6; Object[] parts = _parts; if (first(parts) instanceof Integer) { spacing = (Integer) first(parts); parts = dropFirst(parts); } JPanel panel = vgrid(parts); GridLayout gl = (GridLayout) (panel.getLayout()); gl.setHgap(spacing); gl.setVgap(spacing); return panel; }); } static JPanel northAndCenter(Component n, Component c) { return centerAndNorth(c, n); } static int withBottomMargin_defaultWidth = 6; static JPanel withBottomMargin(Component c) { return withBottomMargin(withBottomMargin_defaultWidth, c); } static JPanel withBottomMargin(final int w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(0, 0, w, 0)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static JPanel smartAddWithLayout(JPanel panel, Object layout, List parts) { for (Object o : parts) panel.add(wrapForSmartAdd(o), layout); return panel; } static JPanel smartAddWithLayout(JPanel panel, Object layout, Object... parts) { return smartAddWithLayout(panel, layout, asList(flattenArray2(parts))); } static Object[] toObjectArray(Collection c) { List l = asList(c); return l.toArray(new Object[l.size()]); } static List nonNulls(Iterable l) { return withoutNulls(l); } static List nonNulls(A[] l) { return withoutNulls(l); } static Map nonNulls(Map map) { return withoutNulls(map); } static Component jrigid() { return javax.swing.Box.createRigidArea(new Dimension(0, 0)); } static A swingConstruct(final Class c, final Object... args) { return swing(new F0() { public A get() { try { return nuObject(c, args); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret nuObject(c, args);"; } }); } static A jPreferHeight(int h, A c) { Dimension size = c.getPreferredSize(); c.setPreferredSize(new Dimension(size.width, max(h, size.height))); return c; } static JPanel jSection(Component c) { return jSection("", c); } static JPanel jSection(final String title, final Component c) { return swing(new F0() { public JPanel get() { try { Border border = BorderFactory.createBevelBorder(BevelBorder.LOWERED); border = BorderFactory.createTitledBorder(border, title); JSection panel = new JSection(c); panel.setBorder(border); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Border border = BorderFactory.createBevelBorder(BevelBorder.LOWERED);\r\n bo..."; } }); } static JPanel jSection(String title) { return jSection(title, jpanel()); } static JPanel jpanel(LayoutManager layout) { return swingNu(JPanel.class, layout); } static JPanel jpanel() { return swingNu(JPanel.class); } static JButton setButtonImage(BufferedImage img, JButton btn) { btn.setIcon(imageIcon(img)); return btn; } static JButton setButtonImage(JButton btn, BufferedImage img) { return setButtonImage(img, btn); } static String sendToLocalBot(String bot, String text, Object... args) { text = format3(text, args); DialogIO channel = findBot(bot); try { if (channel == null) throw fail(quote(bot) + " not found"); try { channel.readLine(); print(bot + "> " + shorten(text, 80)); channel.sendLine(text); String s = channel.readLine(); print(bot + "< " + shorten(s, 80)); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } static String sendToLocalBot(int port, String text, Object... args) { text = format3(text, args); DialogIO channel = talkTo(port); try { try { channel.readLine(); print(port + "> " + shorten(text, 80)); channel.sendLine(text); String s = channel.readLine(); print(port + "< " + shorten(s, 80)); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } static A applyDefaultMargin(final A c) { if (c != null) { swing(new Runnable() { public void run() { try { c.setBorder(BorderFactory.createEmptyBorder(withMargin_defaultWidth, withMargin_defaultWidth, withMargin_defaultWidth, withMargin_defaultWidth)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setBorder(BorderFactory.createEmptyBorder(withMargin_defaultWidth, withMarg..."; } }); } return c; } static A addMargin(final int top, final int left, final int bottom, final int right, final A c) { if (c != null) { swing(new Runnable() { public void run() { try { Border margin = BorderFactory.createEmptyBorder(top, left, bottom, right); c.setBorder(jCompoundBorder(c.getBorder(), margin)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Border margin = BorderFactory.createEmptyBorder(top, left, bottom, right);\r\n ..."; } }); } return c; } static A addMargin(int w, A c) { return addMargin(w, w, w, w, c); } // x = names and components interleaving. // or just components. // or just names. // also, first element can be index of tab to open at start // also, SUPER short demo syntax: jtabs(3) // also, you can pass a Collection containing the elements static JTabbedPane fillJTabs(final JTabbedPane tabs, final Object... _x) { if (tabs == null) return null; clearTabs(tabs); Object[] x = flattenArray2(_x); int idx = 0; if (get(x, 0) instanceof Integer) { idx = asInt(get(x, 0)); x = dropFirst(x); if (empty(x)) { x = arrayrep(null, idx); idx = 0; } } int n = 0; for (int i = 0; i < l(x); i++) { ++n; if (isComponentOrSwingable(x[i])) addTab(tabs, "Tab " + n, wrap(x[i])); else { String name = str(or(x[i], "Tab " + n)); Component c; if (isComponentOrSwingable(get(x, i + 1))) c = wrap(get(x, ++i)); else c = new JPanel(); addTab(tabs, name, wrap(c)); } } if (idx != 0) tabs.setSelectedIndex(min(tabs.getTabCount() - 1, idx)); return tabs; } static JFrame centerPackedFrame(Component c) { centerFrame(packFrame(c)); return getFrame(c); } static A centerFrameWithWidth(int w, A c) { return centerFrame(setFrameWidth(w, c)); } static int getMinimumWidth(final Component c) { return c == null ? 0 : swing(() -> c.getMinimumSize().width); } static boolean amProgram(String snippetID) { return sameSnippetID(programID(), snippetID); } static List concatLists(Iterable... lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) addAll(l, list); return l; } static List concatLists(Collection> lists) { List l = new ArrayList(); if (lists != null) for (Iterable list : lists) addAll(l, list); return l; } static List childrenOfType(Component c, Class theClass) { List l = new ArrayList(); scanForComponents(c, theClass, l); return l; } static List childrenOfType(Class theClass, Component c) { return childrenOfType(c, theClass); } static boolean any(Object pred, Iterable l) { if (l != null) for (A a : l) if (isTrue(callF(pred, a))) return true; return false; } static boolean any(IF1 pred, Iterable l) { return any((Object) pred, l); } static boolean any(Iterable l, IF1 pred) { return any(pred, l); } static boolean any(A[] l, IF1 pred) { if (l != null) for (A a : l) if (pred.get(a)) return true; return false; } static boolean any(Iterable l) { if (l != null) for (Boolean a : l) if (isTrue(a)) return true; return false; } static boolean isInstanceOf(Object o, Class type) { return type.isInstance(o); } public static long parseSnippetID(String snippetID) { long id = Long.parseLong(shortenSnippetID(snippetID)); if (id == 0) throw fail("0 is not a snippet ID"); return id; } static boolean isLocalSnippetID(String snippetID) { return isSnippetID(snippetID) && isLocalSnippetID(psI(snippetID)); } static boolean isLocalSnippetID(long snippetID) { return snippetID >= 1000 && snippetID <= 9999; } static String loadLocalSnippet(String snippetID) { return loadLocalSnippet(psI(snippetID)); } static String loadLocalSnippet(long snippetID) { return loadTextFile(localSnippetFile(snippetID)); } static IResourceLoader vm_getResourceLoader() { return proxy(IResourceLoader.class, vm_generalMap_get("_officialResourceLoader")); } static String fsI(String id) { return formatSnippetID(id); } static String fsI(long id) { return formatSnippetID(id); } static String tb_mainServer_default = "http://code.botcompany.de:8081"; // func -> S static Object tb_mainServer_override; static String tb_mainServer() { if (tb_mainServer_override != null) return (String) callF(tb_mainServer_override); return trim(loadTextFile(tb_mainServer_file(), tb_mainServer_default)); } static File tb_mainServer_file() { return getProgramFile("#1001638", "mainserver.txt"); } static boolean tb_mainServer_isDefault() { return eq(tb_mainServer(), tb_mainServer_default); } static String standardCredentials() { String user = standardCredentialsUser(); String pass = standardCredentialsPass(); if (nempty(user) && nempty(pass)) return "&_user=" + urlencode(user) + "&_pass=" + urlencode(pass); return ""; } static String loadTextFile(String fileName) { return loadTextFile(fileName, null); } static String loadTextFile(File f, String defaultContents) { return loadTextFile(f, defaultContents, "UTF-8"); } static String loadTextFile(File f, String defaultContents, String encoding) { try { checkFileNotTooBigToRead(f); if (f == null || !f.exists()) return defaultContents; FileInputStream fileInputStream = new FileInputStream(f); InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, encoding); return loadTextFile(inputStreamReader); } catch (Exception __e) { throw rethrow(__e); } } public static String loadTextFile(File fileName) { return loadTextFile(fileName, null); } static String loadTextFile(String fileName, String defaultContents) { return fileName == null ? defaultContents : loadTextFile(newFile(fileName), defaultContents); } static String loadTextFile(Reader reader) throws IOException { StringBuilder builder = new StringBuilder(); try { char[] buffer = new char[1024]; int n; while (-1 != (n = reader.read(buffer))) builder.append(buffer, 0, n); } finally { reader.close(); } return str(builder); } static File getGlobalCache() { File file = new File(javaxCachesDir(), "Binary Snippets"); file.mkdirs(); return file; } static A setThreadLocal(ThreadLocal tl, A value) { if (tl == null) return null; A old = tl.get(); tl.set(value); return old; } static int loadPage_defaultTimeout = 60000; static ThreadLocal loadPage_charset = new ThreadLocal(); static boolean loadPage_allowGzip = true, loadPage_debug; // don't send computer ID static boolean loadPage_anonymous = false; static int loadPage_verboseness = 100000; // 60; // seconds static int loadPage_retries = 1; static ThreadLocal loadPage_silent = new ThreadLocal(); // ms static volatile int loadPage_forcedTimeout; // ms static ThreadLocal loadPage_forcedTimeout_byThread = new ThreadLocal(); static ThreadLocal>> loadPage_responseHeaders = new ThreadLocal(); static ThreadLocal> loadPage_extraHeaders = new ThreadLocal(); static ThreadLocal loadPage_sizeLimit = new ThreadLocal(); public static String loadPageSilently(String url) { try { return loadPageSilently(new URL(loadPage_preprocess(url))); } catch (Exception __e) { throw rethrow(__e); } } public static String loadPageSilently(URL url) { try { if (!networkAllowanceTest(str(url))) throw fail("Not allowed: " + url); IOException e = null; for (int tries = 0; tries < loadPage_retries; tries++) try { URLConnection con = loadPage_openConnection(url); return loadPage(con, url); } catch (IOException _e) { e = _e; if (loadPageThroughProxy_enabled) { print("Trying proxy because of: " + e); try { return loadPageThroughProxy(str(url)); } catch (Throwable e2) { print(" " + exceptionToStringShort(e2)); } } else if (loadPage_debug) print(exceptionToStringShort(e)); if (tries < loadPage_retries - 1) sleepSeconds(1); } throw e; } catch (Exception __e) { throw rethrow(__e); } } static String loadPage_preprocess(String url) { if (// don't think we use this anymore url.startsWith("tb/")) url = tb_mainServer() + "/" + url; if (url.indexOf("://") < 0) url = "http://" + url; return url; } static String loadPage(String url) { try { url = loadPage_preprocess(url); if (!isTrue(loadPage_silent.get())) printWithTime("Loading: " + hideCredentials(url)); return loadPageSilently(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static String loadPage(URL url) { return loadPage(url.toExternalForm()); } static String loadPage(URLConnection con, URL url) throws IOException { return loadPage(con, url, true); } static String loadPage(URLConnection con, URL url, boolean addHeaders) throws IOException { Map extraHeaders = getAndClearThreadLocal(loadPage_extraHeaders); Long limit = optPar(loadPage_sizeLimit); if (addHeaders) try { if (!loadPage_anonymous) setHeaders(con); if (loadPage_allowGzip) con.setRequestProperty("Accept-Encoding", "gzip"); con.setRequestProperty("X-No-Cookies", "1"); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); }// fails if within doPost catch (Throwable e) { } vm_generalSubMap("URLConnection per thread").put(currentThread(), con); loadPage_responseHeaders.set(con.getHeaderFields()); InputStream in = null; try { in = urlConnection_getInputStream(con); // vm_generalSubMap("InputStream per thread").put(currentThread(), in); if (loadPage_debug) print("Put stream in map: " + currentThread()); String contentType = con.getContentType(); if (contentType == null) { // printStruct("Headers: ", con.getHeaderFields()); throw new IOException("Page could not be read: " + hideCredentials(url)); } // print("Content-Type: " + contentType); String charset = loadPage_charset == null ? null : loadPage_charset.get(); if (charset == null) charset = loadPage_guessCharset(contentType); if ("gzip".equals(con.getContentEncoding())) { if (loadPage_debug) print("loadPage: Using gzip."); in = newGZIPInputStream(in); } Reader r; try { r = new InputStreamReader(in, unquote(charset)); } catch (UnsupportedEncodingException e) { print(toHex(utf8(charset))); throw e; } boolean silent = isTrue(loadPage_silent.get()); StringBuilder buf = new StringBuilder(); int n = 0; while (limit == null || n < limit) { ping(); int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; if (!silent && (n % loadPage_verboseness) == 0) print(" " + n + " chars read"); } return buf.toString(); } finally { if (loadPage_debug) print("loadPage done"); // vm_generalSubMap("InputStream per thread").remove(currentThread()); vm_generalSubMap("URLConnection per thread").remove(currentThread()); if (in != null) in.close(); } } static String loadPage_guessCharset(String contentType) { Matcher m = regexpMatcher("text/[a-z]+;\\s*charset=([^\\s]+)\\s*", contentType); String match = m.matches() ? m.group(1) : null; if (loadPage_debug) print("loadPage: contentType=" + contentType + ", match: " + match); /* If Content-Type doesn't match this pre-conception, choose default and hope for the best. */ // return or(match, "ISO-8859-1"); return or(match, "UTF-8"); } static URLConnection loadPage_openConnection(URL url) { URLConnection con = openConnection(url); int timeout = toInt(loadPage_forcedTimeout_byThread.get()); if (timeout == 0) timeout = loadPage_forcedTimeout; if (timeout != 0) setURLConnectionTimeouts(con, loadPage_forcedTimeout); else setURLConnectionDefaultTimeouts(con, loadPage_defaultTimeout); return con; } static String defaultFrameTitle() { return autoFrameTitle(); } static void defaultFrameTitle(String title) { autoFrameTitle_value = title; } static A setSize(final A c, final int w, final int h) { if (c != null) { swing(new Runnable() { public void run() { try { c.setSize(w, h); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.setSize(w, h);"; } }); } return c; } static void setSize(Component c, Dimension d) { setSize(c, d.width, d.height); } static A centerFrame(A c) { Window w = getWindow(c); if (w != null) // magic trick w.setLocationRelativeTo(null); return c; } static A centerFrame(int w, int h, A c) { return centerFrame(setFrameSize(w, h, c)); } static JTextArea wrappedTextArea(final JTextArea ta) { enableWordWrapForTextArea(ta); return ta; } static JTextArea wrappedTextArea() { return wrappedTextArea(jtextarea()); } static JTextArea wrappedTextArea(String text) { JTextArea ta = wrappedTextArea(); setText(ta, text); return ta; } static JTextArea enableWordWrapForTextArea(JTextArea ta) { return enableWordWrapForTextArea(ta, true); } static JTextArea enableWordWrapForTextArea(JTextArea ta, boolean enabled) { if (ta != null) { swing(new Runnable() { public void run() { try { ta.setLineWrap(enabled); ta.setWrapStyleWord(true); // Haven't found a way to reliable enable word-wrapping for // an already visible text area // revalidate(enclosingScrollPane(ta)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ta.setLineWrap(enabled);\r\n ta.setWrapStyleWord(true);\r\n // Haven't foun..."; } }); } return ta; } static Font sansSerif(int fontSize) { return new Font(Font.SANS_SERIF, Font.PLAIN, fontSize); } static List buttonsInGroup(ButtonGroup g) { if (g == null) return ll(); return asList(g.getElements()); } static Object vm_generalMap_set(Object key, Object value) { return vm_generalMap_put(key, value); } static Object vm_generalMap_get(Object key) { return vm_generalMap().get(key); } static Set> _entrySet(Map map) { return map == null ? Collections.EMPTY_SET : map.entrySet(); } static float getSwingFontScale() { return or((Float) vm_generalMap_get("swingFontScale_value"), 1f); } static JPanel centerAndSouth(final Component c, final Component s) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.CENTER, wrap(c)); if (s != null) panel.add(BorderLayout.SOUTH, wrap(s)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.CENT..."; } }); } static int withTopMargin_defaultWidth = 6; static JPanel withTopMargin(Component c) { return withTopMargin(withTopMargin_defaultWidth, c); } static JPanel withTopMargin(final int w, final Component c) { return swing(new F0() { public JPanel get() { try { JPanel p = new JPanel(new BorderLayout()); p.setBorder(BorderFactory.createEmptyBorder(w, 0, 0, 0)); p.add(c); return p; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel p = new JPanel(new BorderLayout);\r\n p.setBorder(BorderFactory.creat..."; } }); } static A verticalAlignTop(A a) { return setVerticalAlignment(SwingConstants.TOP, a); } static A verticalAlignTop(A a) { return setVerticalAlignment(SwingConstants.TOP, a); } static String jlabel_textAsHTML(String text) { return hhtml(replace(htmlencode(text), "\n", "
")); } static JPanel centerAndEastWithMarginInbetween(Component c, final Component e) { return centerAndEast(c, withLeftMargin(e)); } static JSplitPane setSplitPaneOnFirstShowing(Component c, double value) { return setSplitPaneOnFirstShowing(c, value, 0); } static JSplitPane setSplitPaneOnFirstShowing(Component c, double value, int delay) { final JSplitPane sp = first(childrenOfType(c, JSplitPane.class)); if (sp != null) onFirstResize(sp, new Runnable() { public void run() { try { if (delay == 0) sp.setDividerLocation(value); else awtLater(delay, new Runnable() { public void run() { try { sp.setDividerLocation(value); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "sp.setDividerLocation(value);"; } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef setSplitPaneOnFirstShowing_debug\r\n printVars setSplitPaneOnFirst..."; } }); return sp; } static JPanel centerAndEast(final Component c, final Component e) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.CENTER, wrap(c)); panel.add(BorderLayout.EAST, wrap(e)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.CENT..."; } }); } static void selectRadioButton(final AbstractButton rb) { if (rb == null) return; { swing(new Runnable() { public void run() { try { rb.setSelected(true); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "rb.setSelected(true);"; } }); } } static void selectRadioButton(ButtonGroup group, int index) { selectRadioButton(get(buttonsInGroup(group), index)); } static JTextField onEnter(final JTextField tf, final Object action) { if (action == null || tf == null) return tf; tf.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { tf.selectAll(); callF(action); } catch (Throwable __e) { messageBox(__e); } } }); return tf; } static JButton onEnter(JButton btn, final Object action) { if (action == null || btn == null) return btn; btn.addActionListener(actionListener(action)); return btn; } static JList onEnter(JList list, Object action) { list.addKeyListener(enterKeyListener(rCallOnSelectedListItem(list, action))); return list; } static JComboBox onEnter(final JComboBox cb, final Object action) { { swing(new Runnable() { public void run() { try { if (cb.isEditable()) { JTextField text = (JTextField) cb.getEditor().getEditorComponent(); onEnter(text, action); } else { cb.getInputMap().put(KeyStroke.getKeyStroke("ENTER"), "enter"); cb.getActionMap().put("enter", abstractAction("", new Runnable() { public void run() { try { cb.hidePopup(); callF(action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "cb.hidePopup(); callF(action);"; } })); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (cb.isEditable()) {\r\n JTextField text = (JTextField) cb.getEditor().g..."; } }); } return cb; } static JTable onEnter(final JTable table, final Object action) { table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter"); table.getActionMap().put("Enter", new AbstractAction() { public void actionPerformed(ActionEvent e) { callF(action, table.getSelectedRow()); } }); return table; } /*static JTextArea onEnter(final JTextArea ta, fO action) { addKeyListener(ta, enterKeyListener(action)); ret ta; }*/ static JTextField onEnter(Object action, JTextField tf) { return onEnter(tf, action); } static ActionListener actionListener(final Object runnable) { return actionListener(runnable, null); } static ActionListener actionListener(final Object runnable, final Object instanceToHold) { if (runnable instanceof ActionListener) return (ActionListener) runnable; final Object info = _threadInfo(); return new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { _threadInheritInfo(info); AutoCloseable __1 = holdInstance(instanceToHold); try { callF(runnable); } finally { _close(__1); } } catch (Throwable __e) { messageBox(__e); } } }; } static Object[] flattenArray2(Object... a) { List l = new ArrayList(); if (a != null) for (Object x : a) if (x instanceof Object[]) l.addAll(asList((Object[]) x)); else if (x instanceof Collection) l.addAll((Collection) x); else l.add(x); return asObjectArray(l); } static Component wrapForSmartAdd(Object o) { if (o == null) return jpanel(); if (o instanceof String) return jlabel((String) o); return wrap(o); } static
A jPreferWidth(int w, A c) { Dimension size = c.getPreferredSize(); c.setPreferredSize(new Dimension(/*max(w, size.width) ??? */ w, size.height)); return c; } static A bindLiveValueListenerToComponent(A component, final LiveValue lv, final Runnable listener) { if (lv != null) bindToComponent(component, new Runnable() { public void run() { try { lv.onChangeAndNow(listener); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef bindLiveValueListenerToComponent_debug\r\n print(\"bindLiveValueL..."; } }, new Runnable() { public void run() { try { lv.removeOnChangeListener(listener); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "lv.removeOnChangeListener(listener)"; } }); return component; } static String strOrNull(Object o) { return o == null ? null : str(o); } static A applyMargin(int top, int left, int bottom, int right, A c) { return addMargin(top, left, bottom, right, c); } static A applyMargin(int w, A c) { return addMargin(w, c); } static int packFrame_minw = 150, packFrame_minh = 50; static A packFrame(final A c) { { swing(new Runnable() { public void run() { try { Window w = getWindow(c); if (w != null) { w.pack(); int maxW = getScreenWidth() - 50, maxH = getScreenHeight() - 50; w.setSize(min(maxW, max(w.getWidth(), packFrame_minw)), min(maxH, max(w.getHeight(), packFrame_minh))); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Window w = getWindow(c);\r\n if (w != null) {\r\n w.pack();\r\n int ma..."; } }); } return c; } static JFrame packFrame(ButtonGroup g) { return packFrame(getFrame(g)); } static JLabel jtoplabel(final String text) { return verticalAlignTop(jlabel(text)); } static JLabel jtoplabel() { return verticalAlignTop(jlabel()); } static String containerTag(String tag) { return containerTag(tag, ""); } static String containerTag(String tag, Object contents, Object... params) { String openingTag = hopeningTag(tag, params); String s = str(contents); return openingTag + s + ""; } static String replaceDollarVars_unindentMLS(String s, Object... params) { return replaceDollarVars(unindentMLS(s), params); } static String jlabel_fixImages(String html) { List tok = htmlTok(html); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); { if (!(tagIs(t, "img"))) continue; } Map params = htmlParams(t); String src = params.get("src"); { if (!(isSnippetID(src))) continue; } try { File f = loadImageAsFile(src); params = mapPlus(params, "src", /*f2s(f)*/ f.toURI()); tok.set(i, hopeningTag("img", params)); } catch (Throwable __e) { _handleException(__e); } } return join(tok); } static String tag(String tag) { return htag(tag); } static String tag(String tag, Object contents, Object... params) { return htag(tag, str(contents), params); } static String tag(String tag, StringBuilder contents, Object... params) { return htag(tag, contents, params); } static String tag(String tag, StringBuffer contents, Object... params) { return htag(tag, contents, params); } // one array plus more elements static Object[] arrayPlus(Object[] a1, Object... a2) { return concatArrays(a1, a2); } static JFrame frameMinWidth(JFrame frame, int w) { return minFrameWidth(frame, w); } static JFrame frameMinWidth(int w, JFrame frame) { return minFrameWidth(w, frame); } static JPanel jcenteredbuttons(Object... params) { return jcenteredline(paramsToButtons(params)); } static Map mapKeys(Object func, Map map) { // TODO: this might break when key type changes through func Map m = similarEmptyMap(map); for (Object key : keys(map)) m.put(callF(func, key), map.get(key)); return m; } static Map mapKeys(Map map, Object func) { return mapKeys(func, map); } static Map mapKeys(Map map, IF1 func) { return mapKeys(map, (Object) func); } static Map mapKeys(IF1 func, Map map) { return mapKeys(map, func); } static String dropDollarPrefix(String s) { return dropPrefix("$", s); } static TreeMap litcimap(Object... x) { return litCIMap(x); } // f takes variable without $ sign. if it returns null, variable is kept static String replaceDollarVars_dyn(String s, IF1 f) { if (f == null) return s; return regexpReplaceIC(s, "\\$(\\w+)", matcher -> { String var = matcher.group(1); String val = f.get(var); return val == null ? matcher.group() : str(val); }); } // usually L static String fromLines(Iterable lines) { StringBuilder buf = new StringBuilder(); if (lines != null) for (Object line : lines) buf.append(str(line)).append('\n'); return buf.toString(); } static String fromLines(String... lines) { return fromLines(asList(lines)); } static IterableIterator toLines(File f) { return linesFromFile(f); } static List toLines(String s) { List lines = new ArrayList(); if (s == null) return lines; int start = 0; while (true) { int i = toLines_nextLineBreak(s, start); if (i < 0) { if (s.length() > start) lines.add(s.substring(start)); break; } lines.add(s.substring(start, i)); if (s.charAt(i) == '\r' && i + 1 < s.length() && s.charAt(i + 1) == '\n') i += 2; else ++i; start = i; } return lines; } static int toLines_nextLineBreak(String s, int start) { int n = s.length(); for (int i = start; i < n; i++) { char c = s.charAt(i); if (c == '\r' || c == '\n') return i; } return -1; } static List beginCriticalAction_inFlight = synchroList(); static class CriticalAction { String description; CriticalAction() { } CriticalAction(String description) { this.description = description; } void done() { beginCriticalAction_inFlight.remove(this); } } static CriticalAction beginCriticalAction(String description) { ping(); CriticalAction c = new CriticalAction(description); beginCriticalAction_inFlight.add(c); return c; } static void cleanMeUp_beginCriticalAction() { int n = 0; while (nempty(beginCriticalAction_inFlight)) { int m = l(beginCriticalAction_inFlight); if (m != n) { n = m; try { print("Waiting for " + n2(n, "critical actions") + ": " + join(", ", collect(beginCriticalAction_inFlight, "description"))); } catch (Throwable __e) { _handleException(__e); } } sleepInCleanUp(10); } } public static File mkdirsForFile(File file) { File dir = file.getParentFile(); if (dir != null) { // is null if file is in current dir dir.mkdirs(); if (!dir.isDirectory()) if (dir.isFile()) throw fail("Please delete the file " + f2s(dir) + " - it is supposed to be a directory!"); else throw fail("Unknown IO exception during mkdirs of " + f2s(file)); } return file; } public static String mkdirsForFile(String path) { mkdirsForFile(new File(path)); return path; } static long now_virtualTime; static long now() { return now_virtualTime != 0 ? now_virtualTime : System.currentTimeMillis(); } static File copyFile(File src, File dest) { try { FileInputStream inputStream = new FileInputStream(src.getPath()); FileOutputStream outputStream = newFileOutputStream(dest.getPath()); try { copyStream(inputStream, outputStream); inputStream.close(); } finally { outputStream.close(); } return dest; } catch (Exception __e) { throw rethrow(__e); } } static A printStackTrace(A e) { // we go to system.out now - system.err is nonsense print(getStackTrace(e)); return e; } static void printStackTrace() { printStackTrace(new Throwable()); } static void printStackTrace(String msg) { printStackTrace(new Throwable(msg)); } static void printStackTrace(String msg, Throwable e) { printStackTrace(new Throwable(msg, e)); } static FileOutputStream newFileOutputStream(File path) throws IOException { return newFileOutputStream(path.getPath()); } static FileOutputStream newFileOutputStream(String path) throws IOException { return newFileOutputStream(path, false); } static FileOutputStream newFileOutputStream(File path, boolean append) throws IOException { return newFileOutputStream(path.getPath(), append); } static FileOutputStream newFileOutputStream(String path, boolean append) throws IOException { mkdirsForFile(path); FileOutputStream f = new FileOutputStream(path, append); _registerIO(f, path, true); return f; } static boolean infoMessage_alwaysOnTop = true; static double infoMessage_defaultTime = 5.0; // automatically switches to AWT thread for you static JWindow infoMessage(String text) { return infoMessage(text, infoMessage_defaultTime); } static JWindow infoMessage(final String text, final double seconds) { printHidingCredentials(text); return infoMessage_noprint(text, seconds); } static JWindow infoMessage_noprint(String text) { return infoMessage_noprint(text, infoMessage_defaultTime); } static JWindow infoMessage_noprint(final String _text, final double seconds) { final String text = hideCredentials(_text); if (empty(text)) return null; logQuotedWithDate(infoBoxesLogFile(), text); if (isHeadless()) return null; return (JWindow) swingAndWait(new F0() { public Object get() { try { final JWindow window = showWindow(infoMessage_makePanel(text)); window.setSize(300, 150); moveToTopRightCorner(window); if (infoMessage_alwaysOnTop) window.setAlwaysOnTop(true); if (vmBus_noObjections("shouldShowInfoBox", window, text)) window.setVisible(true); if (seconds != 0) disposeWindowAfter(iround(seconds * 1000), window); return window; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final JWindow window = showWindow(infoMessage_makePanel(text));\r\n window.s..."; } }); } static JWindow infoMessage(Throwable e) { // showConsole(); printStackTrace(e); return infoMessage(exceptionToStringShort(e)); } static File dropExtension(File f) { return f == null ? null : fileInSameDir(f, dropExtension(f.getName())); } static String dropExtension(String s) { return takeFirst(s, smartLastIndexOf(s, '.')); } static ArrayList asList_closeIterator(CloseableIterableIterator it) { AutoCloseable __1 = it; try { return asList(it); } finally { _close(__1); } } static CloseableIterableIterator linesFromFile(File f) { return linesFromFile(f, null); } static CloseableIterableIterator linesFromFile(File f, IResourceHolder resourceHolder) { try { if (!f.exists()) return emptyCloseableIterableIterator(); if (ewic(f.getName(), ".gz")) return linesFromReader(utf8bufferedReader(newGZIPInputStream(f)), resourceHolder); return linesFromReader(utf8bufferedReader(f), resourceHolder); } catch (Exception __e) { throw rethrow(__e); } } static CloseableIterableIterator linesFromFile(String path) { return linesFromFile(path, null); } static CloseableIterableIterator linesFromFile(String path, IResourceHolder resourceHolder) { return linesFromFile(newFile(path), resourceHolder); } static boolean emptyString(String s) { return s == null || s.length() == 0; } static String hideCredentials(URL url) { return url == null ? null : hideCredentials(str(url)); } static String hideCredentials(String url) { try { if (startsWithOneOf(url, "http://", "https://") && isAGIBlueDomain(hostNameFromURL(url))) return url; } catch (Throwable e) { print("HideCredentials", e); } return url.replaceAll("([&?])(_pass|key|cookie)=[^&\\s\"]*", "$1$2="); } static String hideCredentials(Object o) { return hideCredentials(str(o)); } static Throwable innerException2(Throwable e) { if (e == null) return null; while (empty(e.getMessage()) && e.getCause() != null) e = e.getCause(); return e; } static boolean fileHasAnyExtensionAtAll(File f) { return contains(fileName(f), '.'); } static File appendToFileName(File f, String suffix) { return fileAppendToName(f, suffix); } static File appendToFileName(String suffix, File f) { return appendToFileName(f, suffix); } static String addDotPrefix(String s) { return addPrefix(".", s); } static String rjoin(Iterable strings) { return rjoin("", strings); } static String rjoin(String glue, Iterable strings) { if (strings == null) return ""; if (strings instanceof Collection) { if (((Collection) strings).size() == 1) return str(first(((Collection) strings))); } StringBuilder buf = new StringBuilder(); Iterator i = reversed(strings).iterator(); if (i.hasNext()) { buf.append(i.next()); while (i.hasNext()) buf.append(glue).append(i.next()); } return buf.toString(); } static String rjoin(String glue, String... strings) { return join(glue, asVirtualReversedList(strings)); } static String rjoin(Iterable strings, String glue) { return rjoin(glue, strings); } static String rjoin(String[] strings) { return rjoin("", strings); } static Map newDangerousWeakHashMap() { return _registerDangerousWeakMap(synchroMap(new WeakHashMap())); } // initFunction: voidfunc(Map) - is called initially, and after clearing the map static Map newDangerousWeakHashMap(Object initFunction) { return _registerDangerousWeakMap(synchroMap(new WeakHashMap()), initFunction); } static Object callMCWithVarArgs(String method, Object... args) { return call_withVarargs(mc(), method, args); } static Object invokeMethod(Method m, Object o, Object... args) { try { try { return m.invoke(o, args); } catch (InvocationTargetException e) { throw rethrow(getExceptionCause(e)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(e.getMessage() + " - was calling: " + m + ", args: " + joinWithSpace(classNames(args))); } } catch (Exception __e) { throw rethrow(__e); } } static boolean call_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) print("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) { Object arg = args[i]; if (!(arg == null ? !types[i].isPrimitive() : isInstanceX(types[i], arg))) { if (debug) print("Bad parameter " + i + ": " + arg + " vs " + types[i]); return false; } } return true; } static Field makeAccessible(Field f) { try { f.setAccessible(true); } catch (Throwable e) { // Note: The error reporting only works with Java VM option --illegal-access=deny vmBus_send("makeAccessible_error", e, f); } return f; } static Method makeAccessible(Method m) { try { m.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, m); } return m; } static Constructor makeAccessible(Constructor c) { try { c.setAccessible(true); } catch (Throwable e) { vmBus_send("makeAccessible_error", e, c); } return c; } static String _userHome; static String userHome() { if (_userHome == null) return actualUserHome(); return _userHome; } static File userHome(String path) { return new File(userDir(), path); } static String[] drop(int n, String[] a) { n = Math.min(n, a.length); String[] b = new String[a.length - n]; System.arraycopy(a, n, b, 0, b.length); return b; } static Object[] drop(int n, Object[] a) { n = Math.min(n, a.length); Object[] b = new Object[a.length - n]; System.arraycopy(a, n, b, 0, b.length); return b; } static ArrayList toList(A[] a) { return asList(a); } static ArrayList toList(int[] a) { return asList(a); } static ArrayList toList(Set s) { return asList(s); } static ArrayList toList(Iterable s) { return asList(s); } static void deleteConcepts(Collection conceptsOrIDs) { db_mainConcepts().deleteConcepts(asList(conceptsOrIDs)); } static List deleteConcepts(Class c, Object... params) { return deleteConcepts(db_mainConcepts(), c, params); } static List deleteConcepts(Concepts cc, Class c, Object... params) { List l = asList(findConceptsWhere(cc, c, params)); deleteConcepts(l); return l; } static void deleteConcepts(Class c, IF1 pred) { deleteConcepts(db_mainConcepts(), c, pred); } static void deleteConcepts(Concepts cc, Class c, IF1 pred) { deleteConcepts(filter(list(cc, c), pred)); } static List deleteConcepts(Concepts cc) { return deleteConcepts(cc, Concept.class); } static void deleteConcept(long id) { db_mainConcepts().deleteConcept(id); } static void deleteConcept(Concepts concepts, long id) { concepts.deleteConcept(id); } static void deleteConcept(Concept c) { if (c != null) c.delete(); } static void deleteConcept(Concept.Ref ref) { if (ref != null) deleteConcept(ref.get()); } static ArrayList cloneList(Iterable l) { return l instanceof Collection ? cloneList((Collection) l) : asList(l); } static ArrayList cloneList(Collection l) { if (l == null) return new ArrayList(); synchronized (collectionMutex(l)) { return new ArrayList(l); } } // Where we create new concepts static volatile Concepts mainConcepts; static Concepts db_mainConcepts() { if (mainConcepts == null) mainConcepts = newConceptsWithClassFinder(getDBProgramID()); return mainConcepts; } static void cleanMeUp_concepts() { if (db_mainConcepts() != null) db_mainConcepts().cleanMeUp(); // mainConcepts = null; // TODO } static HashMap findClass_cache = new HashMap(); // currently finds only inner classes of class "main" // returns null on not found // this is the simple version that is not case-tolerant static Class findClass(String name) { synchronized (findClass_cache) { if (findClass_cache.containsKey(name)) return findClass_cache.get(name); if (!isJavaIdentifier(name)) return null; Class c; try { c = Class.forName("main$" + name); } catch (ClassNotFoundException e) { c = null; } findClass_cache.put(name, c); return c; } } static Object nuObject(String className, Object... args) { try { return nuObject(classForName(className), args); } catch (Exception __e) { throw rethrow(__e); } } // too ambiguous - maybe need to fix some callers /*static O nuObject(O realm, S className, O... args) { ret nuObject(_getClass(realm, className), args); }*/ static A nuObject(Class c, Object... args) { try { // cached! if (args.length == 0) return nuObjectWithoutArguments(c); Constructor m = nuObject_findConstructor(c, args); makeAccessible(m); return (A) m.newInstance(args); } catch (Exception __e) { throw rethrow(__e); } } static Constructor nuObject_findConstructor(Class c, Object... args) { for (Constructor m : c.getDeclaredConstructors()) { if (!nuObject_checkArgs(m.getParameterTypes(), args, false)) continue; return m; } throw fail("Constructor " + c.getName() + getClasses(args) + " not found" + (args.length == 0 && (c.getModifiers() & java.lang.reflect.Modifier.STATIC) == 0 ? " - hint: it's a non-static class!" : "")); } static boolean nuObject_checkArgs(Class[] types, Object[] args, boolean debug) { if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static int csetAll(Concept c, Object... values) { return cset(c, values); } static int csetAll(Iterable l, Object... values) { int n = 0; for (Concept c : unnull(l)) n += cset(c, values); return n; } static String[] toStringArray(Collection c) { String[] a = new String[l(c)]; Iterator it = c.iterator(); for (int i = 0; i < l(a); i++) a[i] = it.next(); return a; } static String[] toStringArray(Object o) { if (o instanceof String[]) return (String[]) o; else if (o instanceof Collection) return toStringArray((Collection) o); else throw fail("Not a collection or array: " + getClassName(o)); } static String nohup_sanitize(String s) { return empty(s) ? s : takeFirst(50, s.replaceAll("[^.a-zA-Z0-9\\-_]", "")); } static SimpleDateFormat simpleDateFormat_defaultTZ(String format) { SimpleDateFormat sdf = new SimpleDateFormat(format); sdf.setTimeZone(defaultTimeZone()); return sdf; } static A setFrameTitle(A c, final String title) { final Frame f = getAWTFrame(c); if (f != null) { swing(new Runnable() { public void run() { try { f.setTitle(title); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "f.setTitle(title);"; } }); } return c; } static A setFrameTitle(String title, A c) { return setFrameTitle(c, title); } // magically find a field called "frame" in main class :-) static JFrame setFrameTitle(String title) { Object f = getOpt(mc(), "frame"); if (f instanceof JFrame) return setFrameTitle((JFrame) f, title); return null; } static String getFrameTitle(Component c) { JFrame f = getFrame(c); return f == null ? null : f.getTitle(); } static List reversedList(Iterable l) { List x = cloneList(l); Collections.reverse(x); return x; } static String reversedString(String s) { return reverseString(s); } static Set synchroSet() { return synchroHashSet(); } static Set synchroSet(Set set) { return Collections.synchronizedSet(set); } static Set newWeakHashSet() { return synchroWeakHashSet(); } // runnable = Runnable or String (method name) static Thread newThread(Object runnable) { return new Thread(_topLevelErrorHandling(toRunnable(runnable))); } static Thread newThread(Object runnable, String name) { if (name == null) name = defaultThreadName(); return new Thread(_topLevelErrorHandling(toRunnable(runnable)), name); } static Thread newThread(String name, Object runnable) { return newThread(runnable, name); } static A getAndClearThreadLocal(ThreadLocal tl) { A a = tl.get(); tl.set(null); return a; } static void printStackTrace_inPossiblyCancelledThread(Throwable e) { AutoCloseable __1 = tempUncancelThread(); try { System.out.println(getStackTrace_noRecord(e)); } finally { _close(__1); } } static List beforeDelegatingToThread_operations = synchroList(); static void beforeDelegatingToThread(Thread t) { for (Object op : cloneList(beforeDelegatingToThread_operations)) pcallF(op, t); } static void beforeDelegatingToThread_do(Object f) { setAdd(beforeDelegatingToThread_operations, f); } static void cancelAndInterruptThread(Thread t) { if (t == null) return; cancelThread(t); t.interrupt(); } static Either either2(B b) { return new Either(2, b); } static Either either1(A a) { return new Either(1, a); } static List afterDelegatingToThread_operations = synchroList(); static void afterDelegatingToThread(Thread t) { for (Object op : cloneList(afterDelegatingToThread_operations)) pcallF(op, t); } static void afterDelegatingToThread_do(Object f) { setAdd(afterDelegatingToThread_operations, f); } static int toMS_int(double seconds) { return toInt_checked((long) (seconds * 1000)); } static boolean addToCollection(Collection c, A a) { return c != null && c.add(a); } static JPanel hgridWithSpacing(Object... _parts) { return swing(() -> { int spacing = 6; Object[] parts = _parts; if (first(parts) instanceof Integer) { spacing = (Integer) first(parts); parts = dropFirst(parts); } JPanel panel = hgrid(parts); GridLayout gl = (GridLayout) (panel.getLayout()); gl.setHgap(spacing); gl.setVgap(spacing); return panel; }); } static JPanel vstack2(final Object... parts) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.weightx = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.gridwidth = GridBagConstraints.REMAINDER; smartAddWithLayout(panel, gbc, parts); // gbc = (GridBagConstraints) gbc.clone(); // gbc.fill = GridBagConstraints.BOTH; gbc.weighty = 1; panel.add(jrigid(), gbc); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new GridBagLayout);\r\n new GridBagConstraints gbc..."; } }); } static int lengthOfString(String s) { return s == null ? 0 : s.length(); } static File prepareProgramFile(String name) { return mkdirsForFile(getProgramFile(name)); } static File prepareProgramFile(String progID, String name) { return mkdirsForFile(getProgramFile(progID, name)); } static String regexpReplace_direct(String s, String pat, String replacement) { Matcher m = regexp(pat, s); return regexpReplace_direct(m, replacement); } static String regexpReplace_direct(Matcher m, String replacement) { StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, replacement); m.appendTail(buf); return str(buf); } // pred: func(S) -> bool static List splitAtLinePredicate(Object pred, String text) { List lines = toLines(text); List l = new ArrayList(); int i = 0; while (i < l(lines)) { int j = i; while (j < l(lines) && !callPred(pred, lines.get(j))) ++j; if (j > i) l.add(joinLines(lines.subList(i, j))); i = j + 1; } return l; } static boolean isMultipleEqualsLine(String s) { s = trim(s); return l(s) > 1 && allCharactersAre(s, '='); } static List listGetMulti(final List l, List indices) { return map(indices, new F1() { public A get(Integer i) { try { return _get(l, i); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_get(l, i)"; } }); } static String asciiHeading2(String title) { return asciiHeading(title) + "\n"; } static boolean all(Object pred, Iterable l) { if (l != null) for (Object o : l) if (!isTrue(callF(pred, o))) return false; return true; } static boolean all(Iterable l, IF1 f) { if (l != null) for (A a : l) if (!f.get(a)) return false; return true; } static boolean all(IF1 f, Iterable l) { return all(l, f); } static List filterNempty(Collection c) { List l = new ArrayList(); for (String x : unnull(c)) if (nempty(x)) l.add(x); return l; } static int indexOf(List l, A a, int startIndex) { if (l == null) return -1; int n = l(l); for (int i = startIndex; i < n; i++) if (eq(l.get(i), a)) return i; return -1; } static int indexOf(List l, int startIndex, A a) { return indexOf(l, a, startIndex); } static int indexOf(List l, A a) { if (l == null) return -1; return l.indexOf(a); } static int indexOf(String a, String b) { return a == null || b == null ? -1 : a.indexOf(b); } static int indexOf(String a, String b, int i) { return a == null || b == null ? -1 : a.indexOf(b, i); } static int indexOf(String a, char b) { return a == null ? -1 : a.indexOf(b); } static int indexOf(String a, int i, char b) { return indexOf(a, b, i); } static int indexOf(String a, char b, int i) { return a == null ? -1 : a.indexOf(b, i); } static int indexOf(String a, int i, String b) { return a == null || b == null ? -1 : a.indexOf(b, i); } static int indexOf(A[] x, A a) { int n = l(x); for (int i = 0; i < n; i++) if (eq(x[i], a)) return i; return -1; } // static final Map> getOpt_cache = newDangerousWeakHashMap(f getOpt_special_init); static class getOpt_Map extends WeakHashMap { getOpt_Map() { if (getOpt_special == null) getOpt_special = new HashMap(); clear(); } public void clear() { super.clear(); // print("getOpt clear"); put(Class.class, getOpt_special); put(String.class, getOpt_special); } } static final Map> getOpt_cache = _registerDangerousWeakMap(synchroMap(new getOpt_Map())); // static final Map> getOpt_cache = _registerWeakMap(synchroMap(new getOpt_Map)); // just a marker static HashMap getOpt_special; /*static void getOpt_special_init(Map map) { map.put(Class.class, getOpt_special); map.put(S.class, getOpt_special); }*/ static Object getOpt_cached(Object o, String field) { try { if (o == null) return null; Class c = o.getClass(); HashMap map; synchronized (getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } if (map == getOpt_special) { if (o instanceof Class) return getOpt((Class) o, field); /*if (o instanceof S) ret getOpt(getBot((S) o), field);*/ if (o instanceof Map) return ((Map) o).get(field); } Field f = map.get(field); if (f != null) return f.get(o); if (o instanceof DynamicObject) return mapGet2(((DynamicObject) o).fieldValues, field); return null; } catch (Exception __e) { throw rethrow(__e); } } // used internally - we are in synchronized block static HashMap getOpt_makeCache(Class c) { HashMap map; if (isSubtypeOf(c, Map.class)) map = getOpt_special; else { map = new HashMap(); if (!reflection_classesNotToScan().contains(c.getName())) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) { makeAccessible(f); String name = f.getName(); if (!map.containsKey(name)) map.put(name, f); } _c = _c.getSuperclass(); } while (_c != null); } } if (getOpt_cache != null) getOpt_cache.put(c, map); return map; } static Throwable printStackTrace2(Throwable e) { // we go to system.out now - system.err is nonsense print(getStackTrace2(e)); return e; } static void printStackTrace2() { printStackTrace2(new Throwable()); } static void printStackTrace2(String msg) { printStackTrace2(new Throwable(msg)); } static Map _registerThread_threads; // voidfunc(Thread) static Object _onRegisterThread; static Thread _registerThread(Thread t) { if (_registerThread_threads == null) _registerThread_threads = newWeakHashMap(); _registerThread_threads.put(t, true); vm_generalWeakSubMap("thread2mc").put(t, weakRef(mc())); callF(_onRegisterThread, t); return t; } static void _registerThread() { _registerThread(Thread.currentThread()); } static ThreadLocal print_byThread() { synchronized (print_byThread_lock) { if (print_byThread == null) print_byThread = new ThreadLocal(); } return print_byThread; } // f can return false to suppress regular printing // call print_raw within f to actually print something static AutoCloseable tempInterceptPrint(F1 f) { return tempSetThreadLocal(print_byThread(), f); } static String programID; static String getProgramID() { return nempty(programID) ? formatSnippetIDOpt(programID) : "?"; } // TODO: ask JavaX instead static String getProgramID(Class c) { String id = (String) getOpt(c, "programID"); if (nempty(id)) return formatSnippetID(id); return "?"; } static String getProgramID(Object o) { return getProgramID(getMainClass(o)); } static boolean sameSnippetID(String a, String b) { if (!isSnippetID(a) || !isSnippetID(b)) return false; return parseSnippetID(a) == parseSnippetID(b); } // can be set to work on different base dir static File javaxDataDir_dir; static File javaxDataDir() { return javaxDataDir_dir != null ? javaxDataDir_dir : new File(userHome(), "JavaX-Data"); } static File javaxDataDir(String... subs) { return newFile(javaxDataDir(), subs); } static String formatSnippetIDOpt(String s) { return isSnippetID(s) ? formatSnippetID(s) : s; } static volatile String caseID_caseID; static String caseID() { return caseID_caseID; } static void caseID(String id) { caseID_caseID = id; } static Object call_withVarargs(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findStaticMethod(method, args); if (me != null) return invokeMethod(me, null, args); // try varargs List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } { if (!(isStaticMethod(m))) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, null, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found"); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me != null) return invokeMethod(me, o, args); // try varargs List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, o, newArgs); } throw fail("Method " + c.getName() + "." + method + "(" + joinWithComma(classNames(args)) + ") not found"); } } catch (Exception __e) { throw rethrow(__e); } } static Object callOpt_withVarargs(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me == null) { // TODO: varargs return null; } if ((me.getModifiers() & Modifier.STATIC) == 0) return null; return invokeMethod(me, null, args); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(method, args); if (me != null) return invokeMethod(me, o, args); // try varargs List methods = cache.cache.get(method); if (methods != null) methodSearch: for (Method m : methods) { { if (!(m.isVarArgs())) continue; } Object[] newArgs = massageArgsForVarArgsCall(m, args); if (newArgs != null) return invokeMethod(m, o, newArgs); } return null; } } catch (Exception __e) { throw rethrow(__e); } } static List _registerWeakMap_preList; static A _registerWeakMap(A map) { if (javax() == null) { // We're in class init if (_registerWeakMap_preList == null) _registerWeakMap_preList = synchroList(); _registerWeakMap_preList.add(map); return map; } try { call(javax(), "_registerWeakMap", map); } catch (Throwable e) { printException(e); print("Upgrade JavaX!!"); } return map; } static void _onLoad_registerWeakMap() { assertNotNull(javax()); if (_registerWeakMap_preList == null) return; for (Object o : _registerWeakMap_preList) _registerWeakMap(o); _registerWeakMap_preList = null; } static int isAndroid_flag; static boolean isAndroid() { if (isAndroid_flag == 0) isAndroid_flag = System.getProperty("java.vendor").toLowerCase().indexOf("android") >= 0 ? 1 : -1; return isAndroid_flag > 0; } static Boolean isHeadless_cache; static boolean isHeadless() { if (isHeadless_cache != null) return isHeadless_cache; if (isAndroid()) return isHeadless_cache = true; if (GraphicsEnvironment.isHeadless()) return isHeadless_cache = true; // Also check if AWT actually works. // If DISPLAY variable is set but no X server up, this will notice. try { SwingUtilities.isEventDispatchThread(); return isHeadless_cache = false; } catch (Throwable e) { return isHeadless_cache = true; } } static void assertTrue(Object o) { if (!(eq(o, true))) throw fail(str(o)); } static boolean assertTrue(String msg, boolean b) { if (!b) throw fail(msg); return b; } static boolean assertTrue(boolean b) { if (!b) throw fail("oops"); return b; } static volatile boolean licensed_yes = true; static boolean licensed() { if (!licensed_yes) return false; ping_okInCleanUp(); return true; } static void licensed_off() { licensed_yes = false; } static int[] subIntArray(int[] b, int start) { return subIntArray(b, start, l(b)); } static int[] subIntArray(int[] b, int start, int end) { start = max(start, 0); end = min(end, l(b)); if (start == 0 && end == l(b)) return b; if (start >= end) return new int[0]; int[] x = new int[end - start]; System.arraycopy(b, start, x, 0, end - start); return x; } static List stringAsCharacterList(final String s) { if (s == null) return null; return new RandomAccessAbstractList() { final int l = l(s); public int size() { return l; } public Character get(int i) { return s.charAt(i); } }; } static byte[] bytesFromHex(String s) { return hexToBytes(s); } static String dropPrefix(String prefix, String s) { return s == null ? null : s.startsWith(prefix) ? s.substring(l(prefix)) : s; } static int ubyteToInt(byte b) { return b & 0x0FF; } static String autoUnindent(String s) { int n = getIndent(s); if (n == 0) return s; List l = toLines(s); for (int i = 0; i < l(l); i++) l.set(i, substring(l.get(i), n)); return fromLines(l); } static String dropLeadingNewLine(String s) { if (startsWith(s, "\r\n")) return substring(s, 2); if (startsWith(s, "\n")) return substring(s, 1); return s; } static int hexToInt(String s) { return Integer.parseInt(s, 16); } static boolean swic(String a, String b) { return startsWithIgnoreCase(a, b); } static boolean swic(String a, String b, Matches m) { if (!swic(a, b)) return false; m.m = new String[] { substring(a, l(b)) }; return true; } static boolean ewic(String a, String b) { return endsWithIgnoreCase(a, b); } static boolean ewic(String a, String b, Matches m) { return endsWithIgnoreCase(a, b, m); } static boolean containsNewLines(String s) { return containsNewLine(s); } static String jlabel_textAsHTML_center(String text) { return "
" + replace(htmlencode(text), "\n", "
") + "
"; } static Class javax() { return getJavaX(); } static
A or(A a, A b) { return a != null ? a : b; } // PersistableThrowable doesn't hold GC-disturbing class references in backtrace static volatile PersistableThrowable lastException_lastException; static PersistableThrowable lastException() { return lastException_lastException; } static void lastException(Throwable e) { lastException_lastException = persistableThrowable(e); } static void rotateStringBuffer(StringBuffer buf, int max) { try { if (buf == null) return; synchronized (buf) { if (buf.length() <= max) return; try { int newLength = max / 2; int ofs = buf.length() - newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static void rotateStringBuilder(StringBuilder buf, int max) { try { if (buf == null) return; synchronized (buf) { if (buf.length() <= max) return; try { int newLength = max / 2; int ofs = buf.length() - newLength; String newString = buf.substring(ofs); buf.setLength(0); buf.append("[...] ").append(newString); } catch (Exception e) { buf.setLength(0); } buf.trimToSize(); } } catch (Exception __e) { throw rethrow(__e); } } static Object vmBus_wrapArgs(Object... args) { return empty(args) ? null : l(args) == 1 ? args[0] : args; } static void pcallFAll(Collection l, Object... args) { if (l != null) for (Object f : cloneList(l)) pcallF(f, args); } static void pcallFAll(Iterator it, Object... args) { while (it.hasNext()) pcallF(it.next(), args); } static Set vm_busListeners_live_cache; static Set vm_busListeners_live() { if (vm_busListeners_live_cache == null) vm_busListeners_live_cache = vm_busListeners_live_load(); return vm_busListeners_live_cache; } static Set vm_busListeners_live_load() { return vm_generalIdentityHashSet("busListeners"); } static Map vm_busListenersByMessage_live_cache; static Map vm_busListenersByMessage_live() { if (vm_busListenersByMessage_live_cache == null) vm_busListenersByMessage_live_cache = vm_busListenersByMessage_live_load(); return vm_busListenersByMessage_live_cache; } static Map vm_busListenersByMessage_live_load() { return vm_generalHashMap("busListenersByMessage"); } static Map synchroHashMap() { return synchronizedMap(new HashMap()); } static String singleFieldName(Class c) { Set l = listFields(c); if (l(l) != 1) throw fail("No single field found in " + c + " (have " + n(l(l), "fields") + ")"); return first(l); } static Object deref(Object o) { if (o instanceof Derefable) o = ((Derefable) o).get(); return o; } static String intern(String s) { return fastIntern(s); } static String assertIdentifier(String s) { return assertIsIdentifier(s); } static String assertIdentifier(String msg, String s) { return assertIsIdentifier(msg, s); } static B mapGet(Map map, A a) { return map == null || a == null ? null : map.get(a); } static B mapGet(A a, Map map) { return map == null || a == null ? null : map.get(a); } static void dynamicObject_setRawFieldValue(DynamicObject o, Object key, Object value) { if (o == null) return; // double sync, but should be OK here because of locking order o > o.fieldValues synchronized (o) { o.fieldValues = syncMapPut2_createLinkedHashMap((LinkedHashMap) o.fieldValues, key, value); } } static boolean isConceptList(Object o) { if (!(o instanceof List)) return false; List l = (List) o; for (Object x : l) if (!(x instanceof Concept)) return false; return true; } static void dynamicObject_dropRawField(DynamicObject o, Object key) { if (o == null) return; // double sync, but should be OK here because of locking order o > o.fieldValues synchronized (o) { // can drop the inner synchronization when we migrated all users // of fieldValues to synchronizing on the object too o.fieldValues = (LinkedHashMap) syncMapRemove_deleteMapIfEmpty((Map) o.fieldValues, key); } } static boolean isSubtypeOf(Class a, Class b) { // << always hated that method, let's replace it! return b.isAssignableFrom(a); } static Object derefRef(Object o) { if (o instanceof Concept.Ref) o = ((Concept.Ref) o).get(); return o; } static A derefRef(Concept.Ref r) { return r == null ? null : r.get(); } static List lmap(IF1 f, Iterable l) { return lambdaMap(f, l); } static List lmap(IF1 f, A[] l) { return lambdaMap(f, l); } static boolean isTransient(Field f) { return (f.getModifiers() & java.lang.reflect.Modifier.TRANSIENT) != 0; } static int[] emptyIntArray_a = new int[0]; static int[] emptyIntArray() { return emptyIntArray_a; } static char[] emptyCharArray = new char[0]; static char[] emptyCharArray() { return emptyCharArray; } static double[] emptyDoubleArray = new double[0]; static double[] emptyDoubleArray() { return emptyDoubleArray; } static Map emptyMap() { return new HashMap(); } static Object[] emptyObjectArray_a = new Object[0]; static Object[] emptyObjectArray() { return emptyObjectArray_a; } static Graphics2D antiAliasGraphics(BufferedImage img) { return antiAliasOn(createGraphics(img)); } static double parseDouble(String s) { return Double.parseDouble(s); } static Map synchroIdentityHashMap() { return synchroMap(new IdentityHashMap()); } static void mapPut2(Map map, A key, B value) { if (map != null && key != null) if (value != null) map.put(key, value); else map.remove(key); } static boolean isURL(String s) { return startsWithOneOf(s, "http://", "https://", "file:"); } static BufferedImage imageIO_readURL(String url) { try { return ImageIO.read(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static boolean isAbsolutePath(String s) { return s != null && new File(s).isAbsolute(); } static boolean isAbsolutePath(File f) { return f != null && f.isAbsolute(); } public static boolean isSnippetID(String s) { try { parseSnippetID(s); return true; } catch (RuntimeException e) { return false; } } static File imageSnippetsCacheDir() { return javaxCachesDir("Image-Snippets"); } static String snippetImageURL_http(String snippetID) { return snippetImageURL_http(snippetID, "png"); } static String snippetImageURL_http(String snippetID, String contentType) { return replacePrefix("https://", "http://", snippetImageURL(snippetID, contentType)).replace(":8443", ":8080"); } static Field getOpt_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static void addToContainer(Container a, Component... b) { if (a == null) return; { swing(new Runnable() { public void run() { try { for (Component c : unnull(b)) if (c != null) a.add(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (Component c : unnull(b))\r\n if (c != null) \r\n a.add(c);"; } }); } } static Class getClass(String name) { try { return Class.forName(name); } catch (ClassNotFoundException e) { return null; } } static Class getClass(Object o) { return o instanceof Class ? (Class) o : o.getClass(); } static Class getClass(Object realm, String name) { try { try { return getClass(realm).getClassLoader().loadClass(classNameToVM(name)); } catch (ClassNotFoundException e) { return null; } } catch (Exception __e) { throw rethrow(__e); } } static String classNameToVM(String name) { return name.replace(".", "$"); } static boolean isMainProgram() { return creator() == null; } static TimerTask timerTask(final Object r, final java.util.Timer timer) { return new TimerTask() { public void run() { if (!licensed()) timer.cancel(); else pcallF(r); } }; } static String loadPageSilentlyWithTimeout(double timeoutSeconds, String url) { return loadPageSilentlyWithTimeout(url, toMS_int(timeoutSeconds)); } static String loadPageSilentlyWithTimeout(int timeout, String url) { return loadPageSilentlyWithTimeout(url, timeout); } static String loadPageSilentlyWithTimeout(String url, int timeout) { try { url = loadPage_preprocess(url); URL _url = new URL(url); return loadPage(setURLConnectionTimeouts(_url.openConnection(), timeout), _url); } catch (Exception __e) { throw rethrow(__e); } } static long psI(String snippetID) { return parseSnippetID(snippetID); } static boolean isLowerHexString(String s) { for (int i = 0; i < l(s); i++) { char c = s.charAt(i); if (c >= '0' && c <= '9' || c >= 'a' && c <= 'f') { // ok } else return false; } return true; } public static String bytesToHex(byte[] bytes) { return bytesToHex(bytes, 0, bytes.length); } public static String bytesToHex(byte[] bytes, int ofs, int len) { StringBuilder stringBuilder = new StringBuilder(len * 2); for (int i = 0; i < len; i++) { String s = "0" + Integer.toHexString(bytes[ofs + i]); stringBuilder.append(s.substring(s.length() - 2, s.length())); } return stringBuilder.toString(); } static byte[] toUtf8(String s) { try { return s.getBytes(utf8charset()); } catch (Exception __e) { throw rethrow(__e); } } static boolean md5OfFile_verbose = false; static String md5OfFile(String path) { return md5OfFile(newFile(path)); } static String md5OfFile(File f) { try { if (!f.exists()) return "-"; if (md5OfFile_verbose) print("Getting MD5 of " + f); MessageDigest md5 = MessageDigest.getInstance("MD5"); FileInputStream in = new FileInputStream(f); try { byte[] buf = new byte[65536]; int l; while (true) { l = in.read(buf); if (l <= 0) break; md5.update(buf, 0, l); } return bytesToHex(md5.digest()); } finally { _close(in); } } catch (Exception __e) { throw rethrow(__e); } } static String loadTextFilePossiblyGZipped(String fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static String loadTextFilePossiblyGZipped(String fileName, String defaultContents) { File gz = new File(fileName + ".gz"); return gz.exists() ? loadGZTextFile(gz) : loadTextFile(fileName, defaultContents); } static String loadTextFilePossiblyGZipped(File fileName) { return loadTextFilePossiblyGZipped(fileName, null); } static String loadTextFilePossiblyGZipped(File fileName, String defaultContents) { return loadTextFilePossiblyGZipped(fileName.getPath(), defaultContents); } static File getCachedTranspilationFile(String id) { return newFile(getCodeProgramDir(id), "Transpilation"); } static String getProgramName_cache; static String getProgramName() { Lock __0 = downloadLock(); lock(__0); try { if (getProgramName_cache == null) getProgramName_cache = getSnippetTitleOpt(programID()); return getProgramName_cache; } finally { unlock(__0); } } static void _onLoad_getProgramName() { { startThread(new Runnable() { public void run() { try { getProgramName(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "getProgramName();"; } }); } } // Try to get the quoting right... static String smartJoin(String[] args) { if (empty(args)) return ""; if (args.length == 1) return args[0]; String[] a = new String[args.length]; for (int i = 0; i < a.length; i++) a[i] = !isJavaIdentifier(args[i]) && !isQuoted(args[i]) ? quote(args[i]) : args[i]; return join(" ", a); } static String smartJoin(List args) { return smartJoin(toStringArray(args)); } static Object sleepQuietly_monitor = new Object(); static void sleepQuietly() { try { assertFalse(isAWTThread()); synchronized (sleepQuietly_monitor) { sleepQuietly_monitor.wait(); } } catch (Exception __e) { throw rethrow(__e); } } static File getProgramFile(String progID, String fileName) { if (new File(fileName).isAbsolute()) return new File(fileName); return new File(getProgramDir(progID), fileName); } static File getProgramFile(String fileName) { return getProgramFile(getProgramID(), fileName); } static void appendToTextFile(File file, String s) { appendToFile(file, s); } static void appendToTextFile(String file, String s) { appendToTextFile(programFile(file), s); } static String localDateWithMilliseconds(Date time) { return localDateWithMilliseconds(time.getTime()); } static String localDateWithMilliseconds(long time) { SimpleDateFormat format = simpleDateFormat_local("yyyy/MM/dd HH:mm:ss''SSSS"); return format.format(time); } static String localDateWithMilliseconds() { return localDateWithMilliseconds(now()); } static void print_forAllThreads(Object f) { assertNull("todo", print_allThreads); print_allThreads = f; } static Runnable wrapAsActivity(Object r) { return toRunnable(r); } static Runnable toRunnable(final Object o) { if (o instanceof Runnable) return (Runnable) o; return new Runnable() { public void run() { try { callF(o); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callF(o)"; } }; } static Object getConsoleTextArea_gen() { return getOpt(get(getJavaX(), "console"), "textArea"); } static JFrame setFrameHeight(JFrame frame, int h) { if (frame != null) { swing(new Runnable() { public void run() { try { frame.setSize(frame.getWidth(), h); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "frame.setSize(frame.getWidth(), h);"; } }); } return frame; } static JFrame setFrameHeight(int h, JFrame frame) { return setFrameHeight(frame, h); } static void setConsoleInputFontSize(int size) { JTextField input = consoleInputField(); if (input != null) { input.setFont(sansSerif(size)); revalidateFrame(input); } } static JTextField consoleInputField() { Object console = get(getJavaX(), "console"); return (JTextField) getOpt(console, "tfInput"); } static void centerConsoleFrame() { centerFrame(consoleFrame()); } static void setConsoleTitle(String title) { callOpt(consoleFrame_gen(), "setTitle", title); } static Object getFirstNonNullField(Object o, String... fields) { for (String field : unnull(fields)) { Object __1 = getOpt(o, field); if (__1 != null) return __1; } return null; } static A set(A o, String field, Object value) { if (o == null) return null; if (o instanceof Class) set((Class) o, field, value); else try { Field f = set_findField(o.getClass(), field); makeAccessible(f); smartSet(f, o, value); } catch (Exception e) { throw new RuntimeException(e); } return o; } static void set(Class c, String field, Object value) { if (c == null) return; try { Field f = set_findStaticField(c, field); makeAccessible(f); smartSet(f, null, value); } catch (Exception e) { throw new RuntimeException(e); } } static Field set_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Static field '" + field + "' not found in " + c.getName()); } static Field set_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); throw new RuntimeException("Field '" + field + "' not found in " + c.getName()); } static void set(BitSet bs, int idx) { { if (bs != null) bs.set(idx); } } static void setConsoleInput(String text) { consoleSetInput(text); } static JComponent consoleInputFieldOrComboBox() { Object console = get(getJavaX(), "console"); JComboBox cb = (JComboBox) (getOpt(console, "cbInput")); if (cb != null) return cb; return (JTextField) getOpt(console, "tfInput"); } static void ensureDBNotRunning(String name) { if (hasBot(name)) { try { String framesBot = dropSuffix(".", name) + " Frames"; print("Trying to activate frames of running DB: " + framesBot); if (isOK(sendOpt(framesBot, "activate frames")) && isMainProgram()) cleanKill(); } catch (Throwable __e) { _handleException(__e); } throw fail("Already running: " + name); } } static void ensureDBNotRunning() { ensureDBNotRunning(dbBotStandardName()); } static String dbBotStandardName() { String home = userHome(); String name = dbBotName(getDBProgramID()); if (neq(home, actualUserHome())) name += " " + quote(home); return name + "."; } static volatile Android3 dbBot_instance; static Android3 dbBot() { return dbBot(true); } static Android3 dbBot(boolean ensureNotRunning) { return dbBot(dbBotStandardName(), ensureNotRunning); } static Android3 dbBot(String name) { return dbBot(name, true); } static Android3 dbBot(String name, boolean ensureNotRunning) { if (ensureNotRunning) ensureDBNotRunning(name); return dbBot_instance = methodsBot2(name, assertNotNull(db_mainConcepts()), db_standardExposedMethods(), db_mainConcepts().lock); } static void thinAProgramsBackups(String progID, boolean doIt) { List files = new ArrayList(); Map ageMap = new HashMap(); java.util.regex.Pattern pat = regexp("^(.*)\\.backup(20\\d\\d)(\\d\\d)(\\d\\d)-(\\d\\d)$"); // print("Processing backups of program " + progID); File dir = programDir(progID); for (File f : listFilesNotDirs(dir, newFile(dir, "backups"))) { String s = f.getName(); java.util.regex.Matcher matcher = pat.matcher(s); { if (!(matcher.find())) continue; } String originalName = matcher.group(1); { if (!(eq(originalName, "concepts.structure.gz"))) continue; } // print("Found backup: " + sfu(matcherGroups(matcher))); int year = matcherInt(matcher, 2); int month = matcherInt(matcher, 3); int day = matcherInt(matcher, 4); int hour = matcherInt(matcher, 5); long time = timestampFromYMDH(year, month, day, hour); double age = ((now() - time) / 1000.0 / 60 / 60 / 24); // print("Age: " + age + " days"); ageMap.put(f, age); files.add(f); } int numDeleted = 0; sortByMap_inPlace(files, ageMap); double lastAge = -1; for (File f : files) { double age = ageMap.get(f); if (!thinAProgramsBackups_shouldKeep(age, lastAge)) { // print("Deleting: " + f); ++numDeleted; if (doIt) { print("Deleting: " + f); f.delete(); } } else { // print("Keeping: " + f); lastAge = age; } } if (numDeleted != 0) print((doIt ? "Deleted: " : "Would delete: ") + n(numDeleted, "file")); } // age = age in days static boolean thinAProgramsBackups_shouldKeep(double age, double lastAge) { return defaultAgeBasedBackupRetentionStrategy_shouldKeep(age, lastAge); } static String getDBProgramID_id; static String getDBProgramID() { return nempty(getDBProgramID_id) ? getDBProgramID_id : programIDWithCase(); } static AutoCloseable tempDBLock(Concepts concepts) { // NO null propagation this time return tempLock(concepts.lock); } static AutoCloseable tempDBLock() { return tempDBLock(db_mainConcepts()); } // make concept instance that is not connected to DB static A unlisted(Class c, Object... args) { concepts_unlisted.set(true); try { return nuObject(c, args); } finally { concepts_unlisted.set(null); } } static Concept unlisted(String name, Object... args) { Class cc = findClass(name); concepts_unlisted.set(true); try { return cc != null ? nuObject(cc) : new Concept(name); } finally { concepts_unlisted.set(null); } } static boolean checkConceptFields(Concept x, Object... data) { for (int i = 0; i < l(data); i += 2) if (neq(cget(x, (String) data[i]), deref(data[i + 1]))) return false; return true; } static ClassLoader myClassLoader() { return _getClass(mc()).getClassLoader(); } static boolean isImageServerSnippet(long id) { return id >= 1100000 && id < 1200000; } static File loadImageAsFile(String snippetIDOrURL) { try { if (isURL(snippetIDOrURL)) throw fail("not implemented"); if (!isSnippetID(snippetIDOrURL)) throw fail("Not a URL or snippet ID: " + snippetIDOrURL); String snippetID = "" + parseSnippetID(snippetIDOrURL); File file = imageSnippetCacheFile(snippetID); if (fileSize(file) > 0) return file; String imageURL = snippetImageURL_noHttps(snippetID); System.err.println("Loading image: " + imageURL); byte[] data = loadBinaryPage(imageURL); saveBinaryFile(file, data); return file; } catch (Exception __e) { throw rethrow(__e); } } // If you change this, also change DiskSnippetCache_fileToLibID static File DiskSnippetCache_file(long snippetID) { return new File(getGlobalCache(), "data_" + snippetID + ".jar"); } // Data files are immutable, use centralized cache public static File DiskSnippetCache_getLibrary(long snippetID) throws IOException { File file = DiskSnippetCache_file(snippetID); return file.exists() ? file : null; } public static void DiskSnippetCache_putLibrary(long snippetID, byte[] data) throws IOException { saveBinaryFile(DiskSnippetCache_file(snippetID), data); } static byte[] loadDataSnippetImpl(String snippetID) throws IOException { byte[] data; try { URL url = new URL(dataSnippetLink(snippetID)); print("Loading library: " + hideCredentials(url)); try { data = loadBinaryPage(url.openConnection()); } catch (RuntimeException e) { data = null; } if (data == null || data.length == 0) { url = new URL(tb_mainServer() + "/blobs/" + parseSnippetID(snippetID)); print("Loading library: " + hideCredentials(url)); data = loadBinaryPage(url.openConnection()); } print("Bytes loaded: " + data.length); } catch (FileNotFoundException e) { throw new IOException("Binary snippet #" + snippetID + " not found or not public"); } return data; } static long fileSize(String path) { return getFileSize(path); } static long fileSize(File f) { return getFileSize(f); } static File loadDataSnippetToFile(String snippetID) { try { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.loadLibrary(snippetID); return loadDataSnippetToFile_noResourceLoader(snippetID); } catch (Exception __e) { throw rethrow(__e); } } static File loadDataSnippetToFile_noResourceLoader(String snippetID) { try { snippetID = fsI(snippetID); File f = DiskSnippetCache_file(parseSnippetID(snippetID)); List urlsTried = new ArrayList(); List errors = new ArrayList(); try { URL url = addAndReturn(urlsTried, new URL(dataSnippetLink(snippetID))); print("Loading library: " + hideCredentials(url)); try { loadBinaryPageToFile(openConnection(url), f); if (fileSize(f) == 0) throw fail(); } catch (Throwable e) { errors.add(e); url = addAndReturn(urlsTried, new URL(tb_mainServer() + "/blobs/" + psI(snippetID))); print(e); print("Trying other server: " + hideCredentials(url)); loadBinaryPageToFile(openConnection(url), f); print("Got bytes: " + fileSize(f)); } // TODO: check if we hit the "LOADING" message if (fileSize(f) == 0) throw fail(); System.err.println("Bytes loaded: " + fileSize(f)); } catch (Throwable e) { // printStackTrace(e); errors.add(e); throw fail("Binary snippet " + snippetID + " not found or not public. URLs tried: " + allToString(urlsTried) + ", errors: " + allToString(errors)); } return f; } catch (Exception __e) { throw rethrow(__e); } } static void setOptMC(String field, Object value) { setOpt(mc(), field, value); } static A optParam(ThreadLocal tl, A defaultValue) { return optPar(tl, defaultValue); } static A optParam(ThreadLocal tl) { return optPar(tl); } static Object optParam(String name, Map params) { return mapGet(params, name); } // now also takes a map as single array entry static A optParam(Object[] opt, String name, A defaultValue) { int n = l(opt); if (n == 1 && opt[0] instanceof Map) { Map map = (Map) (opt[0]); return map.containsKey(name) ? (A) map.get(name) : defaultValue; } if (!even(l(opt))) throw fail("Odd parameter length"); for (int i = 0; i < l(opt); i += 2) if (eq(opt[i], name)) return (A) opt[i + 1]; return defaultValue; } static Object optParam(Object[] opt, String name) { return optParam(opt, name, null); } static Object optParam(String name, Object[] params) { return optParam(params, name); } static JFrame setFrameIconLater(Component c, final String imageID) { final JFrame frame = getFrame(c); if (frame != null) startThread("Loading Icon", new Runnable() { public void run() { try { final Image i = imageIcon(or2(imageID, "#1005557")).getImage(); swingLater(new Runnable() { public void run() { try { frame.setIconImage(i); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "frame.setIconImage(i);"; } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final Image i = imageIcon(or2(imageID, \"#1005557\")).getImage();\r\n swingL..."; } }); return frame; } static void _initFrame(JFrame f) { myFrames_list.put(f, Boolean.TRUE); standardTitlePopupMenu(f); } static Rectangle defaultNewFrameBounds_r = new Rectangle(300, 100, 500, 400); static Rectangle defaultNewFrameBounds() { return swing(new F0() { public Rectangle get() { try { defaultNewFrameBounds_r.translate(60, 20); if (!screenRectangle().contains(defaultNewFrameBounds_r)) defaultNewFrameBounds_r.setLocation(30 + random(30), 20 + random(20)); return new Rectangle(defaultNewFrameBounds_r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "defaultNewFrameBounds_r.translate(60, 20);\r\n if (!screenRectangle().contai..."; } }); } static String shortClassName(Object o) { if (o == null) return null; Class c = o instanceof Class ? (Class) o : o.getClass(); String name = c.getName(); return shortenClassName(name); } static int boostHashCombine(int a, int b) { return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2)); } static int _hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static AutoCloseable tempHoldInstance(Object o) { return holdInstance(o); } static Object pcallFunction(Object f, Object... args) { try { return callFunction(f, args); } catch (Throwable __e) { _handleException(__e); } return null; } static String defaultThreadName_name; static String defaultThreadName() { if (defaultThreadName_name == null) defaultThreadName_name = "A thread by " + programID(); return defaultThreadName_name; } static void setOpt_raw(Object o, String field, Object value) { try { if (o == null) return; if (o instanceof Class) setOpt_raw((Class) o, field, value); else { Field f = setOpt_raw_findField(o.getClass(), field); if (f != null) { makeAccessible(f); smartSet(f, o, value); } } } catch (Exception __e) { throw rethrow(__e); } } static void setOpt_raw(Class c, String field, Object value) { try { if (c == null) return; Field f = setOpt_raw_findStaticField(c, field); if (f != null) { makeAccessible(f); smartSet(f, null, value); } } catch (Exception __e) { throw rethrow(__e); } } static Field setOpt_raw_findStaticField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static Field setOpt_raw_findField(Class c, String field) { Class _c = c; do { for (Field f : _c.getDeclaredFields()) if (f.getName().equals(field)) return f; _c = _c.getSuperclass(); } while (_c != null); return null; } static void smartSet(Field f, Object o, Object value) throws Exception { try { f.set(o, value); } catch (Exception e) { Class type = f.getType(); // take care of common case (long to int) if (type == int.class && value instanceof Long) value = ((Long) value).intValue(); if (type == LinkedHashMap.class && value instanceof Map) { f.set(o, asLinkedHashMap((Map) value)); return; } try { if (f.getType() == Concept.Ref.class) { f.set(o, ((Concept) o).new Ref((Concept) value)); return; } if (o instanceof Concept.Ref) { f.set(o, ((Concept.Ref) o).get()); return; } } catch (Throwable _e) { } throw e; } } static A setDyn(A o, String key, Object value) { if (o == null) return o; setDynObjectValue(o, key, value); return o; } static List sorted(Collection c, final Object comparator) { List l = cloneList(c); sort(l, makeComparator(comparator)); return l; } static List sorted(Collection c) { List l = cloneList(c); sort(l); return l; } static List methodsStartingWith(Object o, final String prefix) { return filter(allMethodNames(o), new F1() { public Object get(String s) { try { return startsWith(s, prefix); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "startsWith(s, prefix)"; } }); } static List synchroList() { return synchroList(new ArrayList()); } static List synchroList(List l) { return new SynchronizedList(l); } static PersistableThrowable persistableThrowable(Throwable e) { return e == null ? null : new PersistableThrowable(e); } static Throwable innerException(Throwable e) { return getInnerException(e); } static String formatWithThousands(long l) { return formatWithThousandsSeparator(l); } static double fraction(double d) { return d % 1; } static String n_fancy2(long l, String singular, String plural) { return formatWithThousandsSeparator(l) + " " + trim(l == 1 ? singular : plural); } static String n_fancy2(Collection l, String singular, String plural) { return n_fancy2(l(l), singular, plural); } static String n_fancy2(Map m, String singular, String plural) { return n_fancy2(l(m), singular, plural); } static String n_fancy2(Object[] a, String singular, String plural) { return n_fancy2(l(a), singular, plural); } static String n_fancy2(MultiSet ms, String singular, String plural) { return n_fancy2(l(ms), singular, plural); } static boolean interruptThread_verbose = false; static void interruptThread(Thread t) { if (t == null) return; if (interruptThread_verbose) print("Interrupting thread " + t); // note reason in global map vm_threadInterruptionReasonsMap().put(t, getStackTrace()); t.interrupt(); URLConnection c = (URLConnection) (vm_generalSubMap("URLConnection per thread").get(t)); if (c != null) { try { print("Closing URLConnection of interrupted thread."); call(c, "disconnect"); } catch (Throwable __e) { _handleException(__e); } } } static boolean isJavaXClassLoader(ClassLoader cl) { return startsWithOneOf(className(cl), "main$JavaXClassLoader", "x30$JavaXClassLoader"); } static void setOptAll(Object o, Map fields) { if (fields == null) return; for (String field : keys(fields)) setOpt(/*_flex*/ o, field, fields.get(field)); } static void setOptAll(Object o, Object... values) { // values = expandParams(c.getClass(), values); warnIfOddCount(values); for (int i = 0; i + 1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i + 1]; setOpt(o, field, value); } } static void assertFalse(Object o) { if (!(eq(o, false))) throw fail(str(o)); } static boolean assertFalse(boolean b) { if (b) throw fail("oops"); return b; } static boolean assertFalse(String msg, boolean b) { if (b) throw fail(msg); return b; } static Runnable addThreadInfoToRunnable(final Object r) { final Object info = _threadInfo(); return info == null ? asRunnable(r) : new Runnable() { public void run() { try { _inheritThreadInfo(info); callF(r); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_inheritThreadInfo(info); callF(r);"; } }; } static JInternalFrame getInternalFrame(final Object _o) { return _o == null ? null : swing(new F0() { public JInternalFrame get() { try { Object o = _o; if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof JInternalFrame) return (JInternalFrame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n if (o instanceof ButtonGroup) o = first(buttonsInGroup((Button..."; } }); } static A optCast(Class c, Object o) { return isInstance(c, o) ? (A) o : null; } static Window getWindow(Object o) { if (!(o instanceof Component)) return null; return swing(() -> { Component c = (Component) o; while (c != null) { if (c instanceof Window) return ((Window) c); c = c.getParent(); } return null; }); } static void setMenuBar(final JMenuBar mb, final RootPaneContainer f) { { swing(new Runnable() { public void run() { try { call(f, "setJMenuBar", mb); revalidate((Component) f); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(f, \"setJMenuBar\", mb);\r\n revalidate((Component) f);"; } }); } } static void setMenuBar(RootPaneContainer f, JMenuBar mb) { setMenuBar(mb, f); } static boolean isLetterOrDigit(char c) { return Character.isLetterOrDigit(c); } static Pair pair(A a, B b) { return new Pair(a, b); } static Pair pair(A a) { return new Pair(a, a); } static Object[] asArray(List l) { return toObjectArray(l); } static A[] asArray(Class type, List l) { return (A[]) l.toArray((Object[]) Array.newInstance(type, l.size())); } static boolean isMenuSeparatorIndicator(Object o) { return eqOneOf(o, "***", "---", "===", ""); } static boolean isRunnableX(Object o) { if (o == null) return false; if (o instanceof String) return hasMethod(mc(), (String) o); return o instanceof Runnable || hasMethod(o, "get"); } static String or2(String a, String b) { return nempty(a) ? a : b; } static String or2(String a, String b, String c) { return or2(or2(a, b), c); } static String unCurlyBracket(String s) { return tok_unCurlyBracket(s); } static boolean isCurlyBracketed(String s) { return isCurlyBraced(s); } static Frame getAWTFrame(final Object _o) { return swing(new F0() { public Frame get() { try { Object o = _o; /* ifdef HaveProcessing if (o instanceof PApplet) o = ((PApplet) o).getSurface(); endifdef */ if (o instanceof ButtonGroup) o = first(buttonsInGroup((ButtonGroup) o)); if (!(o instanceof Component)) return null; Component c = (Component) o; while (c != null) { if (c instanceof Frame) return (Frame) c; c = c.getParent(); } return null; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "O o = _o;\r\n /*\r\n ifdef HaveProcessing\r\n if (o instanceof PApplet) ..."; } }); } static A optPar(ThreadLocal tl, A defaultValue) { A a = tl.get(); if (a != null) { tl.set(null); return a; } return defaultValue; } static A optPar(ThreadLocal tl) { return optPar(tl, null); } static Object optPar(Object[] params, String name) { return optParam(params, name); } static Object optPar(String name, Object[] params) { return optParam(params, name); } static Object optPar(String name, Map params) { return optParam(name, params); } static A optPar(Object[] params, String name, A defaultValue) { return optParam(params, name, defaultValue); } static A optPar(String name, Object[] params, A defaultValue) { return optParam(params, name, defaultValue); } static boolean boolPar(ThreadLocal tl) { return boolOptParam(tl); } // defaults to false static boolean boolPar(Object[] __, String name) { return boolOptParam(__, name); } static boolean boolPar(String name, Object[] __) { return boolOptParam(__, name); } static boolean boolPar(String name, Map __) { return boolOptParam(name, __); } static boolean boolPar(String name, Object[] params, boolean defaultValue) { return optParam(params, name, defaultValue); } public static boolean isWindows() { return System.getProperty("os.name").contains("Windows"); } static boolean startsWith(String a, String b) { return a != null && a.startsWith(unnull(b)); } static boolean startsWith(String a, char c) { return nemptyString(a) && a.charAt(0) == c; } static boolean startsWith(String a, String b, Matches m) { if (!startsWith(a, b)) return false; m.m = new String[] { substring(a, strL(b)) }; return true; } static boolean startsWith(List a, List b) { if (a == null || listL(b) > listL(a)) return false; for (int i = 0; i < listL(b); i++) if (neq(a.get(i), b.get(i))) return false; return true; } static JMenuItem disableMenuItem(final JMenuItem mi) { if (mi != null) { swing(new Runnable() { public void run() { try { mi.setEnabled(false); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "mi.setEnabled(false);"; } }); } return mi; } static ActionListener actionListenerInNewThread(final Object runnable) { return actionListenerInNewThread(runnable, null); } static ActionListener actionListenerInNewThread(final Object runnable, final Object instanceToHold) { if (runnable instanceof ActionListener) return (ActionListener) runnable; return new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { startThread("Action Listener", new Runnable() { public void run() { try { AutoCloseable __1 = holdInstance(instanceToHold); try { callF(runnable); } finally { _close(__1); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "AutoCloseable __1 = holdInstance(instanceToHold); try {\r\n callF(runnable..."; } }); } catch (Throwable __e) { messageBox(__e); } } }; } static JMenuItem directJMenuItem(Action a) { return new JMenuItem(a) { public Dimension getMaximumSize() { return new Dimension(super.getPreferredSize().width, super.getMaximumSize().height); } }; } static JMenuItem directJMenuItem(String text, Object action) { return directJMenuItem(abstractAction(text, action)); } static Dimension getPreferredSize(final Component c) { return c == null ? null : swing(new F0() { public Dimension get() { try { return c.getPreferredSize(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getPreferredSize();"; } }); } static String selectedItem(JList l) { return getSelectedItem(l); } static String selectedItem(JComboBox cb) { return getSelectedItem(cb); } static int boolToInt(boolean b) { return b ? 1 : 0; } static A _recordNewSwingComponent(A c) { if (c != null) callF((Object) vm_generalMap_get("newSwingComponentRegistry"), (Object) c); return c; } static JComponent componentToJComponent(Component c) { if (c instanceof JComponent) return (JComponent) c; if (c instanceof JFrame) return ((JFrame) c).getRootPane(); if (c == null) return null; throw fail("boohoo " + getClassName(c)); } static JScrollPane jscroll(final Component c) { return swing(new F0() { public JScrollPane get() { try { return new JScrollPane(c); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret new JScrollPane(c);"; } }); } static JTextField standardTextFieldPopupMenu(final JTextField tf) { final WeakReference ref = weakRef(tf); componentPopupMenuItem(tf, "Copy text to clipboard", new Runnable() { public void run() { try { copyTextToClipboard(ref.get().getText()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "copyTextToClipboard(ref.get().getText())"; } }); componentPopupMenuItem(tf, "Paste", new Runnable() { public void run() { try { ref.get().paste(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ref.get().paste()"; } }); return tf; } static A jenableUndoRedo(final A textcomp) { { swing(new Runnable() { public void run() { try { final UndoManager undo = new UndoManager(); vm_generalWeakSet("Undo Managers").add(undo); textcomp.getDocument().addUndoableEditListener(new UndoableEditListener() { public void undoableEditHappened(UndoableEditEvent evt) { undo.addEdit(evt.getEdit()); } }); textcomp.getActionMap().put("Undo", abstractAction("Undo", new Runnable() { public void run() { try { if (undo.canUndo()) undo.undo(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canUndo()) undo.undo()"; } })); textcomp.getActionMap().put("Redo", abstractAction("Redo", new Runnable() { public void run() { try { if (undo.canRedo()) undo.redo(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (undo.canRedo()) undo.redo()"; } })); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo"); textcomp.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo"); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final new UndoManager undo;\r\n vm_generalWeakSet(\"Undo Managers\").add(undo)..."; } }); } return textcomp; } static String strOrEmpty(Object o) { return o == null ? "" : str(o); } static Class fieldType(Object o, String field) { Field f = getField(o, field); return f == null ? null : f.getType(); } // not a very good one static boolean instanceOf(Object o, String className) { if (o == null) return false; String c = o.getClass().getName(); return eq(c, className) || eq(c, "main$" + className); } // better static boolean instanceOf(Object o, Class c) { if (c == null) return false; return c.isInstance(o); } static boolean instanceOf(Class c, Object o) { return instanceOf(o, c); } static A setHorizontalAlignment(final int pos, final A a) { swingCall(a, "setHorizontalAlignment", pos); return a; } static A setHorizontalAlignment(final int pos, final A a) { swingCall(a, "setHorizontalAlignment", pos); return a; } static A setHorizontalAlignment(final int pos, final A a) { swingCall(a, "setHorizontalAlignment", pos); return a; } static JPanel vgrid(List parts) { return vgrid(asArray(parts)); } static JPanel vgrid(Object... parts) { JPanel panel = new JPanel(); panel.setLayout(new GridLayout(parts.length, 1)); smartAdd(panel, parts); return panel; } static JPanel centerAndNorth(final Component c, final Component n) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new BorderLayout()); panel.add(BorderLayout.CENTER, wrap(c)); panel.add(BorderLayout.NORTH, wrap(n)); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new BorderLayout);\r\n panel.add(BorderLayout.CENT..."; } }); } static List withoutNulls(Iterable l) { if (l instanceof List) if (!containsNulls(((List) l))) return ((List) l); List l2 = new ArrayList(); for (A a : l) if (a != null) l2.add(a); return l2; } static Map withoutNulls(Map map) { Map map2 = similarEmptyMap(map); for (A a : keys(map)) if (a != null) { B b = map.get(a); if (b != null) map2.put(a, b); } return map2; } static List withoutNulls(A[] l) { List l2 = new ArrayList(); if (l != null) for (A a : l) if (a != null) l2.add(a); return l2; } static int imageIcon_cacheSize = 10; static boolean imageIcon_verbose = false; static Map imageIcon_cache; static Lock imageIcon_lock = lock(); static ThreadLocal imageIcon_fixGIF = new ThreadLocal(); // not going through BufferedImage preserves animations static ImageIcon imageIcon(String imageID) { try { if (imageID == null) return null; Lock __0 = imageIcon_lock; lock(__0); try { if (imageIcon_cache == null) imageIcon_cache = new MRUCache(imageIcon_cacheSize); imageID = fsI(imageID); ImageIcon ii = imageIcon_cache.get(imageID); if (ii == null) { if (imageIcon_verbose) print("Loading image icon: " + imageID); File f = loadBinarySnippet(imageID); Boolean b = imageIcon_fixGIF.get(); if (!isFalse(b)) ii = new ImageIcon(loadBufferedImageFixingGIFs(f)); else ii = new ImageIcon(f.toURI().toURL()); } else // move to front of cache on access imageIcon_cache.remove(imageID); imageIcon_cache.put(imageID, ii); return ii; } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } // doesn't fix GIFs static ImageIcon imageIcon(File f) { try { return new ImageIcon(f.toURI().toURL()); } catch (Exception __e) { throw rethrow(__e); } } static ImageIcon imageIcon(Image img) { return new ImageIcon(img); } static String format3(String pat, Object... args) { if (args.length == 0) return pat; List tok = javaTokPlusPeriod(pat); int argidx = 0; for (int i = 1; i < tok.size(); i += 2) if (tok.get(i).equals("*")) tok.set(i, format3_formatArg(argidx < args.length ? args[argidx++] : "null")); return join(tok); } static String format3_formatArg(Object arg) { if (arg == null) return "null"; if (arg instanceof String) { String s = (String) arg; return isIdentifier(s) || isNonNegativeInteger(s) ? s : quote(s); } if (arg instanceof Integer || arg instanceof Long) return String.valueOf(arg); return quote(structure(arg)); } static Map findBot_cache = synchroHashMap(); static int findBot_timeout = 5000; static DialogIO findBot(String searchPattern) { // first split off sub-bot suffix String subBot = null; int i = searchPattern.indexOf('/'); if (i >= 0 && (isJavaIdentifier(searchPattern.substring(0, i)) || isInteger(searchPattern.substring(0, i)))) { subBot = searchPattern.substring(i + 1); searchPattern = searchPattern.substring(0, i); if (!isInteger(searchPattern)) searchPattern = "Multi-Port at " + searchPattern + "."; } // assume it's a port if it's an integer if (isInteger(searchPattern)) return talkToSubBot(subBot, talkTo(parseInt(searchPattern))); if (eq(searchPattern, "remote")) return talkToSubBot(subBot, talkTo("second.tinybrain.de", 4999)); Integer port = findBot_cache.get(searchPattern); if (port != null) try { DialogIO io = talkTo("localhost", port); // TODO: implement io.waitForLine(); String line = io.readLineNoBlock(); if (indexOfIgnoreCase(line, searchPattern) == 0) { // put hello string back in call(io, "pushback", line); return talkToSubBot(subBot, io); } } catch (Exception e) { e.printStackTrace(); } List bots = quickBotScan(); // find top-level bots for (ProgramScan.Program p : bots) { if (indexOfIgnoreCase(p.helloString, searchPattern) == 0) { // strict matching - start of hello string only, but case-insensitive findBot_cache.put(searchPattern, p.port); return talkToSubBot(subBot, talkTo("localhost", p.port)); } } // find sub-bots for (ProgramScan.Program p : bots) { String botName = firstPartOfHelloString(p.helloString); boolean isVM = startsWithIgnoreCase(p.helloString, "This is a JavaX VM."); boolean shouldRecurse = startsWithIgnoreCase(botName, "Multi-Port") || isVM; if (shouldRecurse) try { Map subBots = (Map) unstructure(sendToLocalBotQuietly(p.port, "list bots")); for (Number vport : subBots.keySet()) { String name = subBots.get(vport); if (startsWithIgnoreCase(name, searchPattern)) return talkToSubBot(vport.longValue(), talkTo("localhost", p.port)); } } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } return null; } static String quote(Object o) { if (o == null) return "null"; return quote(str(o)); } static String quote(String s) { if (s == null) return "null"; StringBuilder out = new StringBuilder((int) (l(s) * 1.5 + 2)); quote_impl(s, out); return out.toString(); } static void quote_impl(String s, StringBuilder out) { out.append('"'); int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') out.append('\\').append(c); else if (c == '\r') out.append("\\r"); else if (c == '\n') out.append("\\n"); else if (c == '\t') out.append("\\t"); else if (c == '\0') out.append("\\0"); else out.append(c); } out.append('"'); } static int shorten_default = 100; static String shorten(CharSequence s) { return shorten(s, shorten_default); } static String shorten(CharSequence s, int max) { return shorten(s, max, "..."); } static String shorten(CharSequence s, int max, String shortener) { if (s == null) return ""; if (max < 0) return str(s); return s.length() <= max ? str(s) : subCharSequence(s, 0, min(s.length(), max - l(shortener))) + shortener; } static String shorten(int max, CharSequence s) { return shorten(s, max); } static DialogIO talkTo(int port) { return talkTo("localhost", port); } // This is the CONNECT timeout static int talkTo_defaultTimeout = 10000; // Timeout waiting for answers (0 = no timeout) static int talkTo_timeoutForReads = 0; static ThreadLocal> talkTo_byThread = new ThreadLocal(); static DialogIO talkTo(String ip, int port) { try { String full = ip + ":" + port; Map map = talkTo_byThread.get(); if (map != null && map.containsKey(full)) return map.get(full); if (isLocalhost(ip) && port == vmPort()) return talkToThisVM(); return new talkTo_IO(ip, port); } catch (Exception __e) { throw rethrow(__e); } } static class talkTo_IO extends DialogIO { String ip; int port; Socket s; Writer w; BufferedReader in; talkTo_IO(String ip, int port) { this.port = port; this.ip = ip; try { s = new Socket(); try { if (talkTo_timeoutForReads != 0) s.setSoTimeout(talkTo_timeoutForReads); s.connect(new InetSocketAddress(ip, port), talkTo_defaultTimeout); } catch (Throwable e) { throw fail("Tried talking to " + ip + ":" + port, e); } w = new OutputStreamWriter(s.getOutputStream(), "UTF-8"); in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8")); } catch (Exception __e) { throw rethrow(__e); } } boolean isLocalConnection() { return s.getInetAddress().isLoopbackAddress(); } boolean isStillConnected() { return !(eos || s.isClosed()); } void sendLine(String line) { try { Lock __0 = lock; lock(__0); try { w.write(line + "\n"); w.flush(); } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } String readLineImpl() { try { return in.readLine(); } catch (Exception __e) { throw rethrow(__e); } } public void close() { try { if (!noClose) s.close(); } catch (IOException e) { // whatever } } Socket getSocket() { return s; } } static Border jCompoundBorder(Border inner, Border outer) { if (inner == null) return outer; if (outer == null) return inner; return BorderFactory.createCompoundBorder(inner, outer); } static void clearTabs(final JTabbedPane tabs) { if (tabs != null) { swing(new Runnable() { public void run() { try { tabs.removeAll(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tabs.removeAll();"; } }); } } static int asInt(Object o) { return toInt(o); } static Object[] arrayrep(Object a, int n) { return asArray(repeat(a, n)); } static boolean isComponentOrSwingable(Object o) { if (o instanceof Swingable) return true; return o instanceof Component; } static void addTab(JTabbedPane tabs, String title, Component c) { if (tabs != null) { swing(new Runnable() { public void run() { try { tabs.add(title, wrap(c)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tabs.add(title, wrap(c));"; } }); } } static void addTab(JTabbedPane tabs, String title, Swingable c) { if (tabs != null) { swing(new Runnable() { public void run() { try { tabs.add(title, wrap(c)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tabs.add(title, wrap(c));"; } }); } } static A setFrameWidth(int w, A c) { return setFrameWidth(c, w); } static A setFrameWidth(A c, int w) { JFrame f = getFrame(c); if (f != null) f.setSize(w, f.getHeight()); return c; } static void addAll(Collection c, Iterable b) { if (c != null && b != null) for (A a : b) c.add(a); } static boolean addAll(Collection c, Collection b) { return c != null && b != null && c.addAll(b); } static boolean addAll(Collection c, B... b) { return c != null && b != null && c.addAll(Arrays.asList(b)); } static Map addAll(Map a, Map b) { if (a != null) a.putAll(b); return a; } static void scanForComponents(final Component c, final Class theClass, final List l) { if (theClass.isInstance(c)) l.add((A) c); if (c instanceof Container) { swing(new Runnable() { public void run() { try { for (Component comp : ((Container) c).getComponents()) scanForComponents(comp, theClass, l); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "for (Component comp : ((Container) c).getComponents())\r\n scanForComponen..."; } }); } } static String shortenSnippetID(String snippetID) { if (snippetID.startsWith("#")) snippetID = snippetID.substring(1); String httpBlaBla = "http://tinybrain.de/"; if (snippetID.startsWith(httpBlaBla)) snippetID = snippetID.substring(httpBlaBla.length()); return "" + parseLong(snippetID); } static File localSnippetFile(long snippetID) { return localSnippetsDir(snippetID + ".text"); } static File localSnippetFile(String snippetID) { return localSnippetFile(parseSnippetID(snippetID)); } static A proxy(Class intrface, final Object target) { if (target == null) return null; if (isInstance(intrface, target)) return (A) target; return (A) java.lang.reflect.Proxy.newProxyInstance(intrface.getClassLoader(), new Class[] { intrface }, new proxy_InvocationHandler(target)); } static A proxy(Object target, Class intrface) { return proxy(intrface, target); } static String standardCredentialsUser() { return trim(loadTextFile(oneOfTheFiles(javaxSecretDir("tinybrain-username"), userDir(".tinybrain/username")))); } static String standardCredentialsPass() { return trim(loadTextFile(oneOfTheFiles(javaxSecretDir("tinybrain-userpass"), userDir(".tinybrain/userpass")))); } static String urlencode(String x) { try { return URLEncoder.encode(unnull(x), "UTF-8"); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } static ThreadLocal> checkFileNotTooBigToRead_tl = new ThreadLocal(); static void checkFileNotTooBigToRead(File f) { callF(checkFileNotTooBigToRead_tl.get(), f); } // can be set to work on different base dir static File javaxCachesDir_dir; static File javaxCachesDir() { return javaxCachesDir_dir != null ? javaxCachesDir_dir : new File(userHome(), "JavaX-Caches"); } static File javaxCachesDir(String sub) { return newFile(javaxCachesDir(), sub); } static boolean networkAllowanceTest(String url) { return isAllowed("networkAllowanceTest", url); } static final boolean loadPageThroughProxy_enabled = false; static String loadPageThroughProxy(String url) { return null; } static String exceptionToStringShort(Throwable e) { lastException(e); e = getInnerException(e); String msg = hideCredentials(unnull(e.getMessage())); if (msg.indexOf("Error") < 0 && msg.indexOf("Exception") < 0) return baseClassName(e) + prependIfNempty(": ", msg); else return msg; } static void sleepSeconds(double s) { if (s > 0) sleep(round(s * 1000)); } static A printWithTime(A a) { return printWithTime("", a); } static A printWithTime(String s, A a) { print(hmsWithColons() + ": " + s, a); return a; } static void setHeaders(URLConnection con) throws IOException { String computerID = getComputerID_quick(); if (computerID != null) try { con.setRequestProperty("X-ComputerID", computerID); con.setRequestProperty("X-OS", System.getProperty("os.name") + " " + System.getProperty("os.version")); } catch (Throwable e) { // printShortException(e); } } static Map vm_generalSubMap(Object name) { synchronized (get(javax(), "generalMap")) { Map map = (Map) (vm_generalMap_get(name)); if (map == null) vm_generalMap_put(name, map = synchroMap()); return map; } } static InputStream urlConnection_getInputStream(URLConnection con) throws IOException { UnknownHostException lastException = null; for (int _repeat_0 = 0; _repeat_0 < 2; _repeat_0++) { try { if (con instanceof HttpURLConnection) if (((HttpURLConnection) con).getResponseCode() == 500) throw new IOException(joinNemptiesWithColonSpace("Server code 500", tryToReadErrorStreamFromURLConnection(((HttpURLConnection) con)))); return con.getInputStream(); } catch (UnknownHostException e) { lastException = e; print("Retrying because of: " + e); continue; } } throw lastException; } static GZIPInputStream newGZIPInputStream(File f) { return gzInputStream(f); } static GZIPInputStream newGZIPInputStream(InputStream in) { return gzInputStream(in); } static String unquote(String s) { if (s == null) return null; if (startsWith(s, '[')) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i + 1, s.length() - i - 1); } } if (s.length() > 1) { char c = s.charAt(0); if (c == '\"' || c == '\'') { int l = endsWith(s, c) ? s.length() - 1 : s.length(); StringBuilder sb = new StringBuilder(l - 1); for (int i = 1; i < l; i++) { char ch = s.charAt(i); if (ch == '\\') { char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1); // Octal escape? if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; } } sb.append((char) Integer.parseInt(code, 8)); continue; } switch(nextChar) { case '\"': ch = '\"'; break; case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\'': ch = '\''; break; // Hex Unicode: u???? case 'u': if (i >= l - 5) { ch = 'u'; break; } int code = Integer.parseInt("" + s.charAt(i + 2) + s.charAt(i + 3) + s.charAt(i + 4) + s.charAt(i + 5), 16); sb.append(Character.toChars(code)); i += 5; continue; default: // added by Stefan ch = nextChar; } i++; } sb.append(ch); } return sb.toString(); } } // not quoted - return original return s; } static String toHex(byte[] bytes) { return bytesToHex(bytes); } static String toHex(byte[] bytes, int ofs, int len) { return bytesToHex(bytes, ofs, len); } static byte[] utf8(String s) { return toUtf8(s); } static Matcher regexpMatcher(String pat, String s) { return compileRegexp(pat).matcher(unnull(s)); } static URLConnection openConnection(String url) { try { return openConnection(new URL(url)); } catch (Exception __e) { throw rethrow(__e); } } static URLConnection openConnection(URL url) { try { ping(); callOpt(javax(), "recordOpenURLConnection", str(url)); return url.openConnection(); } catch (Exception __e) { throw rethrow(__e); } } static URLConnection setURLConnectionTimeouts(URLConnection con, long timeout) { con.setConnectTimeout(toInt(timeout)); con.setReadTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout || con.getReadTimeout() != timeout) print("Warning: Timeouts not set by JDK."); return con; } static URLConnection setURLConnectionDefaultTimeouts(URLConnection con, long timeout) { if (con.getConnectTimeout() == 0) { con.setConnectTimeout(toInt(timeout)); if (con.getConnectTimeout() != timeout) print("Warning: URL connect timeout not set by JDK."); } if (con.getReadTimeout() == 0) { con.setReadTimeout(toInt(timeout)); if (con.getReadTimeout() != timeout) print("Warning: URL read timeout not set by JDK."); } return con; } static String autoFrameTitle_value; static String autoFrameTitle() { return autoFrameTitle_value != null ? autoFrameTitle_value : getProgramTitle(); } static void autoFrameTitle(Component c) { setFrameTitle(getFrame(c), autoFrameTitle()); } static A setFrameSize(A c, int w, int h) { JFrame f = getFrame(c); if (f != null) f.setSize(w, h); return c; } static A setFrameSize(int w, int h, A c) { return setFrameSize(c, w, h); } static JTextArea jtextarea() { return jTextArea(); } static JTextArea jtextarea(String text) { return jTextArea(text); } static Object vm_generalMap_put(Object key, Object value) { return mapPutOrRemove(vm_generalMap(), key, value); } static Map vm_generalMap_map; static Map vm_generalMap() { if (vm_generalMap_map == null) vm_generalMap_map = (Map) get(javax(), "generalMap"); return vm_generalMap_map; } static A setVerticalAlignment(final int pos, final A a) { if (a != null) { swing(new Runnable() { public void run() { try { a.setVerticalAlignment(pos); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.setVerticalAlignment(pos);"; } }); } return a; } static A setVerticalAlignment(final int pos, final A a) { if (a != null) { swing(new Runnable() { public void run() { try { a.setVerticalAlignment(pos); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "a.setVerticalAlignment(pos);"; } }); } return a; } static String htmlencode(Object o) { return htmlencode(str(o)); } static String htmlencode(String s) { if (s == null) return ""; StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { int cp = s.codePointAt(i); out.append("&#x"); out.append(intToHex_flexLength(cp)); out.append(';'); i += Character.charCount(cp) - 1; } else out.append(c); } return out.toString(); } static void onFirstResize(final Component c, final Object r) { if (c != null && r != null) { swing(new Runnable() { public void run() { try { c.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { c.removeComponentListener(this); pcallF(r); } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.addComponentListener(new ComponentAdapter {\r\n public void componentRes..."; } }); } } // independent timer static void awtLater(int delay, final Object r) { swingLater(delay, r); } static void awtLater(Object r) { swingLater(r); } // dependent timer (runs only when component is visible) static void awtLater(JComponent component, int delay, Object r) { installTimer(component, r, delay, delay, false); } static void awtLater(JFrame frame, int delay, Object r) { awtLater(frame.getRootPane(), delay, r); } static KeyListener enterKeyListener(final Object action) { return new KeyAdapter() { public void keyPressed(KeyEvent ke) { if (ke.getKeyCode() == KeyEvent.VK_ENTER) pcallF(action); } }; } static Runnable rCallOnSelectedListItem(final JList list, final Object action) { return new Runnable() { public void run() { try { pcallF(action, getSelectedItem(list)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcallF(action, getSelectedItem(list))"; } }; } static List> _threadInfo_makers = synchroList(); static Object _threadInfo() { if (empty(_threadInfo_makers)) return null; HashMap map = new HashMap(); pcallFAll(_threadInfo_makers, map); return map; } static List> _threadInheritInfo_retrievers = synchroList(); static void _threadInheritInfo(Object info) { if (info == null) return; pcallFAll(_threadInheritInfo_retrievers, (Map) info); } static ThreadLocal> holdInstance_l = new ThreadLocal(); static AutoCloseable holdInstance(Object o) { if (o == null) return null; listThreadLocalAdd(holdInstance_l, o); return new AutoCloseable() { public void close() { listThreadLocalPopLast(holdInstance_l); } }; } static Object[] asObjectArray(Collection l) { return toObjectArray(l); } static A bindToComponent(final A component, final Runnable onShow, final Runnable onUnShow) { { swing(new Runnable() { public void run() { try { final Var flag = new Var<>(false); component.addAncestorListener(new AncestorListener() { public void ancestorAdded(AncestorEvent event) { if (flag.get()) print("Warning: bindToComponent logic failure"); flag.set(true); pcallF(onShow); } public void ancestorRemoved(AncestorEvent event) { if (!flag.get()) print("Warning: bindToComponent logic failure"); flag.set(false); pcallF(onUnShow); } public void ancestorMoved(AncestorEvent event) { } }); if (component.isShowing()) { // Hopefully this matches the AncestorListener logic flag.set(true); pcallF(onShow); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final Var flag = new(false);\r\n component.addAncestorListener(new ..."; } }); } return component; } static A bindToComponent(A component, Runnable onShow) { return bindToComponent(component, onShow, null); } static int getScreenWidth() { return getScreenSize().width; } static int getScreenHeight() { return getScreenSize().height; } static String hopeningTag(String tag, Map params) { return hopeningTag(tag, mapToParams(params)); } static String hopeningTag(String tag, Object... params) { StringBuilder buf = new StringBuilder(); buf.append("<" + tag); params = unrollParams(params); for (int i = 0; i < l(params); i += 2) { String name = (String) get(params, i); Object val = get(params, i + 1); if (nempty(name) && val != null) { if (val == html_valueLessParam()) buf.append(" " + name); else { String s = str(val); if (!empty(s)) buf.append(" " + name + "=" + htmlQuote(s)); } } } buf.append(">"); return str(buf); } static List htmlTok(String s) { return htmlcoarsetok(s); } static boolean tagIs(String token, String tag) { return token.regionMatches(true, 0, "<" + tag + " ", 0, tag.length() + 2) || token.regionMatches(true, 0, "<" + tag + ">", 0, tag.length() + 2); } static Map htmlParams(String tag) { return getHtmlTagParameters(tag); } static Map mapPlus(Map m, Object... data) { m = cloneMap(m); litmap_impl(m, data); return m; } static String htag(String tag) { return htag(tag, ""); } static String htag(String tag, Object contents, Object... params) { String openingTag = hopeningTag(tag, params); String s = str(contents); if (empty(s) && neqic(tag, "script")) return dropLast(openingTag) + "/>"; return openingTag + s + ""; } static Object[] concatArrays(Object[]... arrays) { int l = 0; for (Object[] a : arrays) l += l(a); Object[] x = new Object[l]; int i = 0; for (Object[] a : arrays) if (a != null) { System.arraycopy(a, 0, x, i, l(a)); i += l(a); } return x; } static JFrame minFrameWidth(JFrame frame, int w) { if (frame != null && frame.getWidth() < w) frame.setSize(w, frame.getHeight()); return frame; } static JFrame minFrameWidth(int w, JFrame frame) { return minFrameWidth(frame, w); } static JPanel jcenteredline(final Component... components) { // ret new CenteredLine(components); return swing(new F0() { public JPanel get() { try { return jFullCenter(hstackWithSpacing(components)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret jFullCenter(hstackWithSpacing(components));"; } }); } static JPanel jcenteredline(List components) { return jcenteredline(asArray(Component.class, components)); } static List paramsToButtons(Object... params) { List l = new ArrayList(); for (int i = 0; i < l(params); i += 2) if (params[i] != null) if (params[i] instanceof JComponent) l.add((JComponent) params[i--]); else l.add(jbutton((String) params[i], params[i + 1])); return l; } static Map similarEmptyMap(Map m) { if (m instanceof TreeMap) return new TreeMap(((TreeMap) m).comparator()); if (m instanceof LinkedHashMap) return new LinkedHashMap(); // default to a hash map return new HashMap(); } static Map similarEmptyMap(Iterable m) { if (m instanceof TreeSet) return new TreeMap(((TreeSet) m).comparator()); if (m instanceof LinkedHashSet) return new LinkedHashMap(); return new HashMap(); } static TreeMap litCIMap(Object... x) { TreeMap map = caseInsensitiveMap(); litmap_impl(map, x); return map; } // f : Matcher -> S static String regexpReplaceIC(String s, String pat, Object f) { return regexReplaceIC(s, pat, f); } static String regexpReplaceIC(String s, String pat, String replacement) { return regexReplaceIC(s, pat, replacement); } static String regexpReplaceIC(String s, String pat, IF1 f) { return regexReplaceIC(s, pat, f); } static List collect(Iterable c, String field) { return collectField(c, field); } static List collect(String field, Iterable c) { return collectField(c, field); } /*ifclass Concept static L collect(Class c, S field) { ret collect(list(c), field); } endif TODO: make translator ignore stuff in ifclass until resolved */ static void sleepInCleanUp(long ms) { try { if (ms < 0) return; Thread.sleep(ms); } catch (Exception __e) { throw rethrow(__e); } } static String f2s(File f) { return f == null ? null : f.getAbsolutePath(); } static String f2s(String s) { return f2s(newFile(s)); } static String f2s(java.nio.file.Path p) { return p == null ? null : f2s(p.toFile()); } static void copyStream(InputStream in, OutputStream out) { try { byte[] buf = new byte[65536]; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); } } catch (Exception __e) { throw rethrow(__e); } } static void _registerIO(Object object, String path, boolean opened) { } static A printHidingCredentials(A o) { print(hideCredentials(str(o))); return o; } static void logQuotedWithDate(String s) { logQuotedWithTime(s); } static void logQuotedWithDate(String logFile, String s) { logQuotedWithTime(logFile, s); } static void logQuotedWithDate(File logFile, String s) { logQuotedWithTime(logFile, s); } static File infoBoxesLogFile() { return new File(javaxDataDir(), "Logs/infoBoxes.txt"); } static JWindow showWindow(Component c) { JWindow w = new JWindow(); w.add(wrap(c)); return w; } static JPanel infoMessage_makePanel(String text) { final JTextArea ta = wrappedTextArea(text); onClick(ta, new Runnable() { public void run() { try { disposeWindow(ta); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "disposeWindow(ta)"; } }); int size = 14; if (l(text) <= 50) size *= 2; else if (l(text) < 100) size = iround(size * 1.5); ta.setFont(typeWriterFont(size)); JScrollPane sp = jscroll(ta); return withMargin(sp); } static int moveToTopRightCorner_inset = 20; static A moveToTopRightCorner(A a) { return moveToTopRightCorner(moveToTopRightCorner_inset, moveToTopRightCorner_inset, a); } static A moveToTopRightCorner(int insetX, int insetY, A a) { Window w = getWindow(a); if (w != null) w.setLocation(getScreenSize().width - w.getWidth() - insetX, insetY); return a; } static boolean vmBus_noObjections(String msg, Object... args) { return !vmBus_anyFalse(msg, args); } static A disposeWindowAfter(int delay, final A w) { if (w != null) swingLater(delay, new Runnable() { public void run() { try { w.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "w.dispose();"; } }); return w; } static A disposeWindowAfter(A w, double seconds) { return disposeWindowAfter(toMS_int(seconds), w); } static A disposeWindowAfter(double seconds, A w) { return disposeWindowAfter(w, seconds); } static File fileInSameDir(File f, String newName) { return newFile(parentFile(f), newName); } static int smartLastIndexOf(String s, char c) { if (s == null) return 0; int i = s.lastIndexOf(c); return i >= 0 ? i : l(s); } static int smartLastIndexOf(List l, A sub) { int i = lastIndexOf(l, sub); return i < 0 ? l(l) : i; } static CloseableIterableIterator emptyCloseableIterableIterator_instance = new CloseableIterableIterator() { public Object next() { throw fail(); } public boolean hasNext() { return false; } }; static CloseableIterableIterator emptyCloseableIterableIterator() { return emptyCloseableIterableIterator_instance; } static CloseableIterableIterator linesFromReader(Reader r) { return linesFromReader(r, null); } static CloseableIterableIterator linesFromReader(Reader r, IResourceHolder resourceHolder) { final BufferedReader br = bufferedReader(r); return holdResource(resourceHolder, iteratorFromFunction_f0_autoCloseable(new F0() { public String get() { try { return readLineFromReaderWithClose(br); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret readLineFromReaderWithClose(br);"; } }, _wrapIOCloseable(r))); } static BufferedReader utf8bufferedReader(InputStream in) { try { return in == null ? null : bufferedReader(_registerIOWrap(new InputStreamReader(in, "UTF-8"), in)); } catch (Exception __e) { throw rethrow(__e); } } static BufferedReader utf8bufferedReader(File f) { try { return utf8bufferedReader(newFileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static boolean startsWithOneOf(String s, String... l) { for (String x : l) if (startsWith(s, x)) return true; return false; } static boolean startsWithOneOf(String s, Matches m, String... l) { for (String x : l) if (startsWith(s, x, m)) return true; return false; } static boolean isAGIBlueDomain(String domain) { return domainIsUnder(domain, theAGIBlueDomain()); } static String hostNameFromURL(String url) { try { return new URL(url).getHost(); } catch (Exception __e) { throw rethrow(__e); } } static File fileAppendToName(File f, String suffix) { return newFile(f.getPath() + suffix); } static String addPrefix(String prefix, String s) { return s.startsWith(prefix) ? s : prefix + s; } static List asVirtualReversedList(A[] array) { return wrapAsReversedList(array); } static List _registerDangerousWeakMap_preList; static A _registerDangerousWeakMap(A map) { return _registerDangerousWeakMap(map, null); } static A _registerDangerousWeakMap(A map, Object init) { callF(init, map); if (init instanceof String) { final String f = (String) init; init = new VF1() { public void get(Map map) { try { callMC(f, map); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "callMC(f, map)"; } }; } if (javax() == null) { // We're in class init if (_registerDangerousWeakMap_preList == null) _registerDangerousWeakMap_preList = synchroList(); _registerDangerousWeakMap_preList.add(pair(map, init)); return map; } call(javax(), "_registerDangerousWeakMap", map, init); return map; } static void _onLoad_registerDangerousWeakMap() { assertNotNull(javax()); if (_registerDangerousWeakMap_preList == null) return; for (Pair p : _registerDangerousWeakMap_preList) _registerDangerousWeakMap(p.a, p.b); _registerDangerousWeakMap_preList = null; } static Throwable getExceptionCause(Throwable e) { Throwable c = e.getCause(); return c != null ? c : e; } static String joinWithSpace(Iterable c) { return join(" ", c); } static String joinWithSpace(String... c) { return join(" ", c); } static List classNames(Collection l) { return getClassNames(l); } static List classNames(Object[] l) { return getClassNames(Arrays.asList(l)); } static boolean isInstanceX(Class type, Object arg) { if (type == boolean.class) return arg instanceof Boolean; if (type == int.class) return arg instanceof Integer; if (type == long.class) return arg instanceof Long; if (type == float.class) return arg instanceof Float; if (type == short.class) return arg instanceof Short; if (type == char.class) return arg instanceof Character; if (type == byte.class) return arg instanceof Byte; if (type == double.class) return arg instanceof Double; return type.isInstance(arg); } static String actualUserHome_value; static String actualUserHome() { if (actualUserHome_value == null) { if (isAndroid()) actualUserHome_value = "/storage/emulated/0/"; else actualUserHome_value = System.getProperty("user.home"); } return actualUserHome_value; } static File actualUserHome(String sub) { return newFile(new File(actualUserHome()), sub); } static Collection findConceptsWhere(Class c, Object... params) { return findConceptsWhere(db_mainConcepts(), c, params); } static Collection findConceptsWhere(String c, Object... params) { return findConceptsWhere(db_mainConcepts(), c, params); } static Collection findConceptsWhere(Concepts concepts, Class c, Object... params) { ping(); params = expandParams(c, params); // indexed if (concepts.fieldIndices != null) for (int i = 0; i < l(params); i += 2) { IFieldIndex index = concepts.getFieldIndex(c, (String) params[i]); if (index != null) { Collection rawList = index.getAll(params[i + 1]); params = dropEntryFromParams(params, i); if (params == null) return rawList; List l = new ArrayList(); for (A x : rawList) if (checkConceptFields(x, params)) l.add(x); return l; } } // table scan return filterConcepts(concepts.list(c), params); } static Collection findConceptsWhere(Concepts concepts, String c, Object... params) { return filterConcepts(concepts.list(c), params); } static List filter(Iterable c, Object pred) { if (pred instanceof F1) return filter(c, (F1) pred); List x = new ArrayList(); if (c != null) for (Object o : c) if (isTrue(callF(pred, o))) x.add(o); return x; } static List filter(Object pred, Iterable c) { return filter(c, pred); } static List filter(Iterable c, F1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static List filter(F1 pred, Iterable c) { return filter(c, pred); } // ifclass IF1 static List filter(Iterable c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static List filter(B[] c, IF1 pred) { List x = new ArrayList(); if (c != null) for (B o : c) if (pred.get(o)) x.add(o); return x; } static List filter(IF1 pred, Iterable c) { return filter(c, pred); } // endif static List list(Class type) { return db_mainConcepts().list(type); } static List list(Concepts concepts, Class type) { return concepts.list(type); } static List list(String type) { return db_mainConcepts().list(type); } static List list(Concepts concepts, String type) { return concepts.list(type); } static Object collectionMutex(List l) { return l; } static Object collectionMutex(Object o) { if (o instanceof List) return o; String c = className(o); if (eq(c, "java.util.TreeMap$KeySet")) c = className(o = getOpt(o, "m")); else if (eq(c, "java.util.HashMap$KeySet")) c = className(o = get_raw(o, "this$0")); if (eqOneOf(c, "java.util.TreeMap$AscendingSubMap", "java.util.TreeMap$DescendingSubMap")) c = className(o = get_raw(o, "m")); return o; } static Concepts newConceptsWithClassFinder(String progID) { Concepts cc = new Concepts(progID); cc.classFinder = _defaultClassFinder(); return cc; } static boolean isJavaIdentifier(String s) { if (empty(s) || !Character.isJavaIdentifierStart(s.charAt(0))) return false; for (int i = 1; i < s.length(); i++) if (!Character.isJavaIdentifierPart(s.charAt(i))) return false; return true; } static Map classForName_cache = synchroHashMap(); static Class classForName(String name) { try { // in class init if (classForName_cache == null) return Class.forName(name); Class c = classForName_cache.get(name); if (c == null) classForName_cache.put(name, c = Class.forName(name)); return c; } catch (Exception __e) { throw rethrow(__e); } } static Map nuObjectWithoutArguments_cache = newDangerousWeakHashMap(); static Object nuObjectWithoutArguments(String className) { try { return nuObjectWithoutArguments(classForName(className)); } catch (Exception __e) { throw rethrow(__e); } } static A nuObjectWithoutArguments(Class c) { try { if (nuObjectWithoutArguments_cache == null) // in class init return (A) nuObjectWithoutArguments_findConstructor(c).newInstance(); Constructor m = nuObjectWithoutArguments_cache.get(c); if (m == null) nuObjectWithoutArguments_cache.put(c, m = nuObjectWithoutArguments_findConstructor(c)); return (A) m.newInstance(); } catch (Exception __e) { throw rethrow(__e); } } static Constructor nuObjectWithoutArguments_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (empty(m.getParameterTypes())) { makeAccessible(m); return m; } throw fail("No default constructor found in " + c.getName()); } static List getClasses(Object[] array) { List l = emptyList(l(array)); for (Object o : array) l.add(_getClass(o)); return l; } static TimeZone defaultTimeZone() { return TimeZone.getDefault(); } static String reverseString(String s) { return new StringBuilder(s).reverse().toString(); } // TODO: OurSyncCollections static Set synchroHashSet() { return Collections.synchronizedSet(new HashSet()); } static Set synchroWeakHashSet() { return Collections.newSetFromMap((Map) newWeakHashMap()); } static Runnable _topLevelErrorHandling(final Runnable runnable) { final Object info = _threadInfo(); return new Runnable() { public void run() { try { try { _threadInheritInfo(info); runnable.run(); } catch (Throwable __e) { _handleException(__e); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "pcall {\r\n _threadInheritInfo(info);\r\n runnable.run();\r\n }"; } }; } static AutoCloseable tempUncancelThread() { return tempRemove(ping_actions, Thread.currentThread()); } static boolean setAdd(Collection c, A a) { if (c == null || c.contains(a)) return false; c.add(a); return true; } static void cancelThread(Thread t) { if (t == null) return; ping(); /*O mc = getWeakRef((WeakReference) vm_generalWeakSubMap("thread2mc").get(t)); ifdef cancelThread_verbose print("cancelThread: mc=" + mc); endifdef if (mc != null) { Map ping_actions = cast get(mc, 'ping_actions); synchronized(ping_actions) { ping_actions.put(t, "cancelled"); set(mc, ping_anyActions := true); } } else*/ synchronized (ping_actions) { ping_actions.put(t, "cancelled"); ping_anyActions = true; } } static int toInt_checked(long l) { if (l != (int) l) throw fail("Too large for int: " + l); return (int) l; } static JPanel hgrid(final Object... parts) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(); Object[] _parts = flattenArray2(parts); panel.setLayout(new GridLayout(1, _parts.length)); smartAdd(panel, _parts); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "new JPanel panel;\r\n O[] _parts = flattenArray2(parts);\r\n panel.setLayou..."; } }); } static Matcher regexp(String pat, String s) { return regexp(compileRegexp(pat), unnull(s)); } static Matcher regexp(java.util.regex.Pattern pat, String s) { return pat.matcher(unnull(s)); } static java.util.regex.Pattern regexp(String pat) { return compileRegexp(pat); } static boolean callPred(Object condition, Object... args) { return isTrue(callF(condition, args)); } static String joinLines(List lines) { return fromLines(lines); } static String joinLines(String glue, String text) { return join(glue, toLines(text)); } static boolean allCharactersAre(String s, char c) { int n = l(s); for (int i = 0; i < n; i++) if (s.charAt(i) != c) return false; return true; } static A _get(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static Object _get(Object o, String field) { return get(o, field); } static Object _get(String field, Object o) { return get(o, field); } static A _get(A[] l, int idx) { return idx >= 0 && idx < l(l) ? l[idx] : null; } static String asciiHeading(String title) { return "\n" + title + "\n" + rep(l(title), '-'); } static Map myFrames_list = weakHashMap(); static List myFrames() { return swing(new F0>() { public List get() { try { return keysList(myFrames_list); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret keysList(myFrames_list);"; } }); } static void clear(Collection c) { if (c != null) c.clear(); } static void clear(Map map) { if (map != null) map.clear(); } static void put(Map map, A a, B b) { if (map != null) map.put(a, b); } static void put(List l, int i, A a) { if (l != null && i >= 0 && i < l(l)) l.set(i, a); } static B mapGet2(Map map, A a) { return map == null ? null : map.get(a); } static B mapGet2(A a, Map map) { return map == null ? null : map.get(a); } static Set reflection_classesNotToScan_value = litset("jdk.internal.loader.URLClassPath"); static Set reflection_classesNotToScan() { return reflection_classesNotToScan_value; } static String getStackTrace2(Throwable e) { return hideCredentials(getStackTrace(unwrapTrivialExceptionWraps(e)) + replacePrefix("java.lang.RuntimeException: ", "FAIL: ", hideCredentials(str(innerException2(e)))) + "\n"); } static Map vm_generalWeakSubMap(Object name) { synchronized (get(javax(), "generalMap")) { Map map = (Map) (vm_generalMap_get(name)); if (map == null) vm_generalMap_put(name, map = newWeakMap()); return map; } } static WeakReference weakRef(A a) { return newWeakReference(a); } static AutoCloseable tempSetThreadLocal(final ThreadLocal tl, A a) { if (tl == null) return null; final A prev = setThreadLocal(tl, a); return new AutoCloseable() { public String toString() { return "tl.set(prev);"; } public void close() throws Exception { tl.set(prev); } }; } static Class getMainClass() { return mc(); } static Class getMainClass(Object o) { try { if (o == null) return null; if (o instanceof Class && eq(((Class) o).getName(), "x30")) return (Class) o; ClassLoader cl = (o instanceof Class ? (Class) o : o.getClass()).getClassLoader(); if (cl == null) return null; String name = mainClassNameForClassLoader(cl); return cl.loadClass(name); } catch (Exception __e) { throw rethrow(__e); } } static final Map callOpt_cache = newDangerousWeakHashMap(); static Object callOpt_cached(Object o, String methodName, Object... args) { try { if (o == null) return null; if (o instanceof Class) { Class c = (Class) o; _MethodCache cache = callOpt_getCache(c); // TODO: (super-rare) case where method exists static and non-static // with different args Method me = cache.findMethod(methodName, args); if (me == null || (me.getModifiers() & Modifier.STATIC) == 0) return null; return invokeMethod(me, null, args); } else { Class c = o.getClass(); _MethodCache cache = callOpt_getCache(c); Method me = cache.findMethod(methodName, args); if (me == null) return null; return invokeMethod(me, o, args); } } catch (Exception __e) { throw rethrow(__e); } } static _MethodCache callOpt_getCache(Class c) { synchronized (callOpt_cache) { _MethodCache cache = callOpt_cache.get(c); if (cache == null) callOpt_cache.put(c, cache = new _MethodCache(c)); return cache; } } static boolean isStaticMethod(Method m) { return methodIsStatic(m); } static Object[] massageArgsForVarArgsCall(Method m, Object[] args) { Class[] types = m.getParameterTypes(); int n = types.length - 1, nArgs = args.length; if (nArgs < n) return null; for (int i = 0; i < n; i++) if (!argumentCompatibleWithType(args[i], types[i])) return null; Class varArgType = types[n].getComponentType(); for (int i = n; i < nArgs; i++) if (!argumentCompatibleWithType(args[i], varArgType)) return null; Object[] newArgs = new Object[n + 1]; arraycopy(args, 0, newArgs, 0, n); Object[] varArgs = arrayOfType(varArgType, nArgs - n); arraycopy(args, n, varArgs, 0, nArgs - n); newArgs[n] = varArgs; return newArgs; } static A printException(A e) { printStackTrace(e); return e; } static A assertNotNull(A a) { assertTrue(a != null); return a; } static A assertNotNull(String msg, A a) { assertTrue(msg, a != null); return a; } static byte[] hexToBytes(String s) { if (odd(l(s))) throw fail("Hex string has odd length: " + quote(shorten(10, s))); int n = l(s) / 2; byte[] bytes = new byte[n]; for (int i = 0; i < n; i++) { int a = parseHexChar(s.charAt(i * 2)); int b = parseHexChar(s.charAt(i * 2 + 1)); if (a < 0 || b < 0) throw fail("Bad hex byte: " + quote(substring(s, i * 2, i * 2 + 2)) + " at " + i * 2 + "/" + l(s)); bytes[i] = (byte) ((a << 4) | b); } return bytes; } static int getIndent(String s) { int n = Integer.MAX_VALUE; for (String l : toLines(s)) n = min(n, getIndentOfLine(l)); return n; } static boolean startsWithIgnoreCase(String a, String b) { return regionMatchesIC(a, 0, b, 0, b.length()); } static boolean endsWithIgnoreCase(String a, String b) { int la = l(a), lb = l(b); return la >= lb && regionMatchesIC(a, la - lb, b, 0, lb); } static boolean endsWithIgnoreCase(String a, String b, Matches m) { if (!endsWithIgnoreCase(a, b)) return false; if (m != null) m.m = new String[] { substring(a, 0, l(a) - l(b)) }; return true; } static boolean containsNewLine(String s) { // screw \r, nobody needs it return contains(s, '\n'); } static Set vm_generalIdentityHashSet(Object name) { synchronized (get(javax(), "generalMap")) { Set set = (Set) (vm_generalMap_get(name)); if (set == null) vm_generalMap_put(name, set = syncIdentityHashSet()); return set; } } static Map vm_generalHashMap(Object name) { synchronized (get(javax(), "generalMap")) { Map m = (Map) (vm_generalMap_get(name)); if (m == null) vm_generalMap_put(name, m = syncHashMap()); return m; } } static Map synchronizedMap() { return synchroMap(); } static Map synchronizedMap(Map map) { return synchroMap(map); } // This is for main classes that are all static. // (We don't go to base classes.) static Set listFields(Object c) { TreeSet fields = new TreeSet(); for (Field f : _getClass(c).getDeclaredFields()) fields.add(f.getName()); return fields; } static String n(long l, String name) { return l + " " + trim(l == 1 ? singular(name) : getPlural(name)); } static String n(Collection l, String name) { return n(l(l), name); } static String n(Map m, String name) { return n(l(m), name); } static String n(Object[] a, String name) { return n(l(a), name); } static String n(MultiSet ms, String name) { return n(l(ms), name); } static Method fastIntern_method; static String fastIntern(String s) { try { if (s == null) return null; if (fastIntern_method == null) { fastIntern_method = findMethodNamed(javax(), "internPerProgram"); if (fastIntern_method == null) upgradeJavaXAndRestart(); } return (String) fastIntern_method.invoke(null, s); } catch (Exception __e) { throw rethrow(__e); } } static String assertIsIdentifier(String s) { if (!isIdentifier(s)) throw fail("Not an identifier: " + quote(s)); return s; } static String assertIsIdentifier(String msg, String s) { if (!isIdentifier(s)) throw fail(msg + " - Not an identifier: " + quote(s)); return s; } static LinkedHashMap syncMapPut2_createLinkedHashMap(LinkedHashMap map, A key, B value) { if (key != null) if (value != null) { if (map == null) map = new LinkedHashMap(); synchronized (collectionMutex(map)) { map.put(key, value); } } else if (map != null) synchronized (collectionMutex(map)) { map.remove(key); } return map; } static > C syncMapRemove_deleteMapIfEmpty(C map, A key) { if (map != null && key != null) synchronized (collectionMutex(map)) { map.remove(key); if (map.isEmpty()) return null; } return map; } static List lambdaMap(IF1 f, Iterable l) { return map(l, f); } static List lambdaMap(IF1 f, A[] l) { return map(l, f); } static Graphics2D antiAliasOn(Graphics2D g) { g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); return g; } static String replacePrefix(String prefix, String replacement, String s) { if (!startsWith(s, prefix)) return s; return replacement + substring(s, l(prefix)); } static String snippetImageURL(long snippetID) { return snippetImageURL(fsI(snippetID)); } static String snippetImageURL(String snippetID) { return snippetImageURL(snippetID, "png"); } static String snippetImageURL(String snippetID, String contentType) { if (snippetID == null || isURL(snippetID)) return snippetID; long id = parseSnippetID(snippetID); String url; if (isImageServerSnippet(id)) url = imageServerLink(id); else // url = "http://eyeocr.sourceforge.net/filestore/filestore.php?cmd=serve&file=blob_" + id + "&contentType=image/" + contentType; url = "https://botcompany.de/img/" + id; return url; } static WeakReference creator_class; static Object creator() { return creator_class == null ? null : creator_class.get(); } static Charset utf8charset_cache; static Charset utf8charset() { if (utf8charset_cache == null) utf8charset_cache = utf8charset_load(); return utf8charset_cache; } static Charset utf8charset_load() { return Charset.forName("UTF-8"); } static String loadGZTextFile(File file) { try { if (!file.isFile()) return null; ping(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream fis = new FileInputStream(file); try { GZIPInputStream gis = newGZIPInputStream(fis); byte[] buffer = new byte[1024]; int len; while ((len = gis.read(buffer)) != -1) baos.write(buffer, 0, len); baos.close(); // TODO: use a Reader return fromUtf8(baos.toByteArray()); } finally { _close(fis); } } catch (Exception __e) { throw rethrow(__e); } } static File getCodeProgramDir() { return getCodeProgramDir(getProgramID()); } static File getCodeProgramDir(String snippetID) { return new File(javaxCodeDir(), formatSnippetID(snippetID)); } static File getCodeProgramDir(long snippetID) { return getCodeProgramDir(formatSnippetID(snippetID)); } static Lock downloadLock_lock = fairLock(); static Lock downloadLock() { return downloadLock_lock; } static void lock(Lock lock) { try { ping(); if (lock == null) return; try { lock.lockInterruptibly(); } catch (InterruptedException e) { Object reason = vm_threadInterruptionReasonsMap().get(currentThread()); print("Locking interrupted! Reason: " + strOr(reason, "Unknown")); printStackTrace(e); rethrow(e); } // NO call to ping here! Make sure lock is always released. } catch (Exception __e) { throw rethrow(__e); } } static void lock(Lock lock, String msg) { print("Locking: " + msg); lock(lock); } static void lock(Lock lock, String msg, long timeout) { print("Locking: " + msg); lockOrFail(lock, timeout); } static ReentrantLock lock() { return fairLock(); } static String getSnippetTitleOpt(String s) { return isSnippetID(s) ? getSnippetTitle(s) : s; } static void unlock(Lock lock, String msg) { if (lock == null) return; lock.unlock(); // print afterwards to make sure the lock is always unlocked print("Unlocked: " + msg); } static void unlock(Lock lock) { if (lock == null) return; lock.unlock(); } // supports the usual quotings (", variable length double brackets) except ' quoting static boolean isQuoted(String s) { // use the exact version if (isNormalQuoted(s)) return true; return isMultilineQuoted(s); } static File getProgramDir() { return programDir(); } static File getProgramDir(String snippetID) { return programDir(snippetID); } static Lock appendToFile_lock = lock(); static boolean appendToFile_keepOpen = false; static HashMap appendToFile_writers = new HashMap(); static void appendToFile(String path, String s) { try { Lock __0 = appendToFile_lock; lock(__0); try { // Let's just generally synchronize this to be safe. mkdirsForFile(new File(path)); path = getCanonicalPath(path); Writer writer = appendToFile_writers.get(path); if (writer == null) { // print("[Logging to " + path + "]"); writer = new BufferedWriter(new OutputStreamWriter(newFileOutputStream(path, true), "UTF-8")); if (appendToFile_keepOpen) appendToFile_writers.put(path, writer); } writer.write(s); if (!appendToFile_keepOpen) writer.close(); } finally { unlock(__0); } } catch (Exception __e) { throw rethrow(__e); } } static void appendToFile(File path, String s) { if (path != null) appendToFile(path.getPath(), s); } static void cleanMeUp_appendToFile() { AutoCloseable __3 = tempCleaningUp(); try { Lock __1 = appendToFile_lock; lock(__1); try { closeAllWriters(values(appendToFile_writers)); appendToFile_writers.clear(); } finally { unlock(__1); } } finally { _close(__3); } } static SimpleDateFormat simpleDateFormat_local(String format) { SimpleDateFormat sdf = new SimpleDateFormat(format); sdf.setTimeZone(localTimeZone()); return sdf; } static A assertNull(A a) { assertTrue(a == null); return a; } static A assertNull(String msg, A a) { assertTrue(msg, a == null); return a; } static void revalidateFrame(Component c) { revalidate(getFrame(c)); } static Object consoleFrame_gen() { return getOpt(getOpt(getJavaX(), "console"), "frame"); } static void consoleSetInput(final String text) { if (headless()) return; setTextAndSelectAll(consoleInputField(), text); focusConsole(); } static boolean hasBot(String searchPattern) { try { DialogIO io = findBot(searchPattern); if (io != null) { io.close(); return true; } else return false; } catch (Exception __e) { throw rethrow(__e); } } static String dropSuffix(String suffix, String s) { return s.endsWith(suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static boolean isOK(String s) { s = trim(s); return swic(s, "ok ") || eqic(s, "ok") || matchStart("ok", s); } static String sendOpt(String bot, String text, Object... args) { return sendToLocalBotOpt(bot, text, args); } static void cleanKill() { cleanKillVM(); } static String dbBotName(String progIDWithCase) { return fsI_flex(progIDWithCase) + " Concepts"; } static Android3 methodsBot2(String name, final Object receiver, final List exposedMethods) { return methodsBot2(name, receiver, exposedMethods, null); } static Android3 methodsBot2(String name, final Object receiver, final List exposedMethods, final Lock lock) { Android3 android = new Android3(); android.greeting = name; android.console = false; android.responder = new Responder() { String answer(String s, List history) { return exposeMethods2(receiver, s, exposedMethods, lock); } }; return makeBot(android); } static List db_standardExposedMethods_list = ll("xlist", "xnew", "xset", "xdelete", "xget", "xclass", "xfullgrab", "xshutdown", "xchangeCount", "xcount"); static List db_standardExposedMethods() { return db_standardExposedMethods_list; } static List listFilesNotDirs(String dir) { return listFilesOnly(dir); } static List listFilesNotDirs(File... dirs) { return listFilesOnly(dirs); } static int matcherInt(Matcher m, int i) { return parseInt(m.group(i)); } // month = 1 to 12 static long timestampFromYMDH(int y, int m, int d, int h) { return new GregorianCalendar(y, m - 1, d, h, 0).getTimeInMillis(); } static List sortByMap_inPlace(List l, Map map) { sort(l, mapComparator(map)); return l; } // age = age in days, lastAge = age of last (more recent) file kept (also in days) static boolean defaultAgeBasedBackupRetentionStrategy_shouldKeep(double age, double lastAge) { // keep all backups of last 12 hours if (age <= 0.5) return true; // keep every daily backup from this week if (age <= 7 && age >= lastAge + 1) return true; // weekly backups for 3 more weeks if (age <= 28 && age >= lastAge + 7) return true; // after 4 weeks, switch to monthly (roundabout) if (age >= lastAge + 365.0 / 12) return true; return false; } static String programIDWithCase() { return nempty(caseID()) ? programID() + "/" + quoteUnlessIdentifierOrInteger(caseID()) : programID(); } // accept purpose argument so we are a drop-in for tempVerboseLock static AutoCloseable tempLock(Lock lock) { return tempLock("", lock); } static AutoCloseable tempLock(String purpose, Lock lock) { if (lock == null) return null; lock(lock); return new AutoCloseable() { public String toString() { return "unlock(lock);"; } public void close() throws Exception { unlock(lock); } }; } static File imageSnippetCacheFile(String snippetID) { File dir = imageSnippetsCacheDir(); if (!loadBufferedImage_useImageCache) return null; return new File(dir, parseSnippetID(snippetID) + ".png"); } static String snippetImageURL_noHttps(String snippetID) { return snippetImageURL_noHttps(snippetID, "png"); } static String snippetImageURL_noHttps(String snippetID, String contentType) { return snippetImageURL(snippetID, contentType).replace("https://www.botcompany.de:8443/", "http://www.botcompany.de:8080/").replace("https://botcompany.de/", "http://botcompany.de/"); } static ThreadLocal>> loadBinaryPage_responseHeaders = new ThreadLocal(); static ThreadLocal> loadBinaryPage_extraHeaders = new ThreadLocal(); static byte[] loadBinaryPage(String url) { try { print("Loading " + url); return loadBinaryPage(loadPage_openConnection(new URL(url))); } catch (Exception __e) { throw rethrow(__e); } } static byte[] loadBinaryPage(URLConnection con) { try { Map extraHeaders = getAndClearThreadLocal(loadBinaryPage_extraHeaders); setHeaders(con); for (String key : keys(extraHeaders)) con.setRequestProperty(key, extraHeaders.get(key)); return loadBinaryPage_noHeaders(con); } catch (Exception __e) { throw rethrow(__e); } } static byte[] loadBinaryPage_noHeaders(URLConnection con) { try { ByteArrayOutputStream buf = new ByteArrayOutputStream(); InputStream inputStream = con.getInputStream(); loadBinaryPage_responseHeaders.set(con.getHeaderFields()); long len = 0; try { len = con.getContentLength(); } catch (Throwable e) { printStackTrace(e); } int n = 0; while (true) { int ch = inputStream.read(); if (ch < 0) break; buf.write(ch); if (++n % 100000 == 0) println(" " + n + (len != 0 ? "/" + len : "") + " bytes loaded."); } inputStream.close(); return buf.toByteArray(); } catch (Exception __e) { throw rethrow(__e); } } /** * writes safely (to temp file, then rename) */ public static byte[] saveBinaryFile(String fileName, byte[] contents) { try { File file = new File(fileName); File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); String tempFileName = fileName + "_temp"; FileOutputStream fileOutputStream = newFileOutputStream(tempFileName); fileOutputStream.write(contents); fileOutputStream.close(); if (file.exists() && !file.delete()) throw new IOException("Can't delete " + fileName); if (!new File(tempFileName).renameTo(file)) throw new IOException("Can't rename " + tempFileName + " to " + fileName); vmBus_send("wroteFile", file); return contents; } catch (Exception __e) { throw rethrow(__e); } } static byte[] saveBinaryFile(File fileName, byte[] contents) { return saveBinaryFile(fileName.getPath(), contents); } static String dataSnippetLink(String snippetID) { long id = parseSnippetID(snippetID); if (id >= 1100000 && id < 1200000) return imageServerURL() + id; if (id >= 1200000 && id < 1300000) { // Woody files, actually String pw = muricaPassword(); if (empty(pw)) throw fail("Please set 'murica password by running #1008829"); // XXX, although it typically gets hidden when printing return "https://botcompany.de/files/" + id + "?_pass=" + pw; } return fileServerURL() + "/" + id; } static void loadBinaryPageToFile(String url, File file) { try { print("Loading " + url); loadBinaryPageToFile(openConnection(new URL(url)), file); } catch (Exception __e) { throw rethrow(__e); } } static void loadBinaryPageToFile(URLConnection con, File file) { try { setHeaders(con); loadBinaryPageToFile_noHeaders(con, file); } catch (Exception __e) { throw rethrow(__e); } } static void loadBinaryPageToFile_noHeaders(URLConnection con, File file) { try { File ftemp = new File(f2s(file) + "_temp"); FileOutputStream buf = newFileOutputStream(mkdirsFor(ftemp)); try { InputStream inputStream = con.getInputStream(); long len = 0; try { len = con.getContentLength(); } catch (Throwable e) { printStackTrace(e); } String pat = " {*}" + (len != 0 ? "/" + len : "") + " bytes loaded."; copyStreamWithPrints(inputStream, buf, pat); inputStream.close(); buf.close(); file.delete(); renameFile_assertTrue(ftemp, file); } finally { if (buf != null) buf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static boolean even(int i) { return (i & 1) == 0; } static boolean even(long i) { return (i & 1) == 0; } static boolean even(BigInteger n) { return even(n.intValue()); } static void standardTitlePopupMenu(final JFrame frame) { // standard right-click behavior on titles if (!isSubstanceLAF()) return; titlePopupMenu(frame, new VF1() { public void get(JPopupMenu menu) { try { boolean alwaysOnTop = frame.isAlwaysOnTop(); menu.add(jmenuItem("Restart Program", "restart")); menu.add(jmenuItem("Duplicate Program", "duplicateThisProgram")); menu.add(jmenuItem("Show Console", "showConsole")); menu.add(jCheckBoxMenuItem("Always On Top", alwaysOnTop, new Runnable() { public void run() { try { toggleAlwaysOnTop(frame); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "toggleAlwaysOnTop(frame)"; } })); /*ifndef standardTitlePopupMenu_noShootWindow { menu.add(jMenuItem("Shoot Window", r { shootWindowGUI_external(frame, 500) })); } endifndef*/ // addMenuItem(menu, "Bigger fonts", f swingBiggerFonts); // addMenuItem(menu, "Smaller fonts", f swingSmallerFonts); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "bool alwaysOnTop = frame.isAlwaysOnTop();\r\n ifndef standardTitlePopupMenu_..."; } }); } static Rectangle screenRectangle() { return new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); } static Rectangle screenRectangle(GraphicsDevice device) { if (device == null) return null; DisplayMode mode = device.getDisplayMode(); return new Rectangle(0, 0, mode.getWidth(), mode.getHeight()); } static Random random_random = new Random(); static int random(int n) { return random(random_random, n); } static int random(int n, Random r) { return random(r, n); } static int random(Random r, int n) { return n <= 0 ? 0 : r.nextInt(n); } static double random(double max) { return random() * max; } static double random() { return random_random.nextInt(100001) / 100000.0; } static double random(double min, double max) { return min + random() * (max - min); } // min <= value < max static int random(int min, int max) { return min + random(max - min); } static int random(int min, int max, Random r) { return random(r, min, max); } static int random(Random r, int min, int max) { return min + random(r, max - min); } static A random(List l) { return oneOf(l); } static A random(Collection c) { if (c instanceof List) return random((List) c); int i = random(l(c)); return collectionGet(c, i); } static String shortenClassName(String name) { if (name == null) return null; int i = lastIndexOf(name, "$"); if (i < 0) i = lastIndexOf(name, "."); return i < 0 ? name : substring(name, i + 1); } static Object callFunction(Object f, Object... args) { return callF(f, args); } static LinkedHashMap asLinkedHashMap(Map map) { if (map instanceof LinkedHashMap) return (LinkedHashMap) map; LinkedHashMap m = new LinkedHashMap(); if (map != null) synchronized (collectionMutex(map)) { m.putAll(map); } return m; } static void setDynObjectValue(DynamicObject o, String field, Object value) { dynamicObject_setRawFieldValue(o, field, value); } static void sort(T[] a, Comparator c) { if (a != null) Arrays.sort(a, c); } static void sort(T[] a) { if (a != null) Arrays.sort(a); } static void sort(int[] a) { if (a != null) Arrays.sort(a); } static void sort(List a, Comparator c) { if (a != null) Collections.sort(a, c); } static void sort(List a) { if (a != null) Collections.sort(a); } static Comparator makeComparator(final Object f) { if (f instanceof Comparator) return (Comparator) f; return new Comparator() { public int compare(Object a, Object b) { return (Integer) callF(f, a, b); } }; } static List allMethodNames(Object o) { Class c = _getClass(o); TreeSet names = new TreeSet(); while (c != null) { for (Method m : c.getDeclaredMethods()) names.add(m.getName()); c = c.getSuperclass(); } return asList(names); } static Throwable getInnerException(Throwable e) { if (e == null) return null; while (e.getCause() != null) e = e.getCause(); return e; } static Throwable getInnerException(Runnable r) { return getInnerException(getException(r)); } static String formatWithThousandsSeparator(long l) { return NumberFormat.getInstance(new Locale("en_US")).format(l); } static Map vm_threadInterruptionReasonsMap() { return vm_generalWeakSubMap("Thread interruption reasons"); } static String className(Object o) { return getClassName(o); } static Runnable asRunnable(Object o) { return toRunnable(o); } static void _inheritThreadInfo(Object info) { _threadInheritInfo(info); } static boolean isInstance(Class type, Object arg) { return type.isInstance(arg); } static boolean eqOneOf(Object o, Object... l) { for (Object x : l) if (eq(o, x)) return true; return false; } static boolean hasMethod(Object o, String method, Object... args) { return findMethod_cached(o, method, args) != null; } static String tok_unCurlyBracket(String s) { return isCurlyBraced(s) ? join(dropFirstThreeAndLastThree(javaTok(s))) : s; } static boolean isCurlyBraced(String s) { List tok = tok_combineCurlyBrackets_keep(javaTok(s)); return l(tok) == 3 && startsWithAndEndsWith(tok.get(1), "{", "}"); } static boolean boolOptParam(ThreadLocal tl) { return isTrue(optPar(tl)); } // defaults to false static boolean boolOptParam(Object[] __, String name) { return isTrue(optParam(__, name)); } static boolean boolOptParam(String name, Object[] __) { return boolOptParam(__, name); } static boolean boolOptParam(String name, Map __) { return isTrue(optPar(name, __)); } static boolean nemptyString(String s) { return s != null && s.length() > 0; } static int listL(Collection l) { return l == null ? 0 : l.size(); } static String getSelectedItem(JList l) { return (String) l.getSelectedValue(); } static String getSelectedItem(JComboBox cb) { return strOrNull(cb.getSelectedItem()); } static A componentPopupMenuItem(A c, final String name, final Object action) { componentPopupMenu(c, new VF1() { public void get(JPopupMenu menu) { try { addMenuItem(menu, name, action); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, name, action);"; } }); return c; } static void componentPopupMenuItem(JComponent c, final JMenuItem menuItem) { componentPopupMenu(c, new VF1() { public void get(JPopupMenu menu) { try { addMenuItem(menu, menuItem); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, menuItem);"; } }); } static String copyTextToClipboard(Object _text) { String text = str(_text); StringSelection selection = new StringSelection(text); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); vmBus_send("newClipboardContents", text); return text; } static Set vm_generalWeakSet(Object name) { synchronized (get(javax(), "generalMap")) { Set set = (Set) (vm_generalMap_get(name)); if (set == null) vm_generalMap_put(name, set = newWeakHashSet()); return set; } } static Field getField(Object o, String field) { if (o == null) return null; return setOpt_findField(_getClass(o), field); } static Object getField(Field field, Object o) { return fieldGet(field, o); } static boolean containsNulls(Collection c) { return contains(c, null); } static boolean loadBufferedImageFixingGIFs_debug = false; static ThreadLocal> loadBufferedImageFixingGIFs_output = new ThreadLocal(); static Image loadBufferedImageFixingGIFs(File file) { try { if (!file.exists()) return null; // Load anything but GIF the normal way if (!isGIF(file)) return ImageIO.read(file); if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": checking gif"); // Get GIF reader ImageReader reader = ImageIO.getImageReadersByFormatName("gif").next(); // Give it the stream to decode from reader.setInput(ImageIO.createImageInputStream(file)); int numImages = reader.getNumImages(true); // Get 'metaFormatName'. Need first frame for that. IIOMetadata imageMetaData = reader.getImageMetadata(0); String metaFormatName = imageMetaData.getNativeMetadataFormatName(); // Find out if GIF is bugged boolean foundBug = false; for (int i = 0; i < numImages && !foundBug; i++) { // Get metadata IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(i).getAsTree(metaFormatName); // Find GraphicControlExtension node int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { // Get delay value String delay = ((IIOMetadataNode) node).getAttribute("delayTime"); // Check if delay is bugged if (Integer.parseInt(delay) == 0) { foundBug = true; } break; } } } if (loadBufferedImageFixingGIFs_debug) print("loadBufferedImageFixingGIFs" + ": " + f2s(file) + " foundBug=" + foundBug); // Load non-bugged GIF the normal way Image image; if (!foundBug) { image = Toolkit.getDefaultToolkit().createImage(f2s(file)); } else { // Prepare streams for image encoding ByteArrayOutputStream baoStream = new ByteArrayOutputStream(); { ImageOutputStream ios = ImageIO.createImageOutputStream(baoStream); try { // Get GIF writer that's compatible with reader ImageWriter writer = ImageIO.getImageWriter(reader); // Give it the stream to encode to writer.setOutput(ios); writer.prepareWriteSequence(null); for (int i = 0; i < numImages; i++) { // Get input image BufferedImage frameIn = reader.read(i); // Get input metadata IIOMetadataNode root = (IIOMetadataNode) reader.getImageMetadata(i).getAsTree(metaFormatName); // Find GraphicControlExtension node int nNodes = root.getLength(); for (int j = 0; j < nNodes; j++) { org.w3c.dom.Node node = root.item(j); if (node.getNodeName().equalsIgnoreCase("GraphicControlExtension")) { // Get delay value String delay = ((IIOMetadataNode) node).getAttribute("delayTime"); // Check if delay is bugged if (Integer.parseInt(delay) == 0) { // Overwrite with a valid delay value ((IIOMetadataNode) node).setAttribute("delayTime", "10"); } break; } } // Create output metadata IIOMetadata metadata = writer.getDefaultImageMetadata(new ImageTypeSpecifier(frameIn), null); // Copy metadata to output metadata metadata.setFromTree(metadata.getNativeMetadataFormatName(), root); // Create output image IIOImage frameOut = new IIOImage(frameIn, null, metadata); // Encode output image writer.writeToSequence(frameOut, writer.getDefaultWriteParam()); } writer.endWriteSequence(); } finally { _close(ios); } } // Create image using encoded data byte[] data = baoStream.toByteArray(); setVar(loadBufferedImageFixingGIFs_output.get(), data); if (loadBufferedImageFixingGIFs_debug) print("Data size: " + l(data)); image = Toolkit.getDefaultToolkit().createImage(data); } return image; } catch (Exception __e) { throw rethrow(__e); } } // This is made for NL parsing. // It's javaTok extended with "..." token, "$n" and "#n" and // special quotes (which are converted to normal ones). static List javaTokPlusPeriod(String s) { List tok = new ArrayList(); if (s == null) return tok; int l = s.length(); int i = 0; while (i < l) { int j = i; char c; String cc; // scan for whitespace while (j < l) { c = s.charAt(j); cc = s.substring(j, Math.min(j + 2, l)); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (cc.equals("/*")) { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (cc.equals("//")) { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); cc = s.substring(i, Math.min(i + 2, l)); // scan for non-whitespace // normalize quotes if (c == (char) 0x201C || c == (char) 0x201D) c = '"'; if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { char _c = s.charAt(j); // normalize quotes if (_c == (char) 0x201C || _c == (char) 0x201D) _c = '"'; if (_c == opener) { ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } if (j - 1 >= i + 1) { tok.add(opener + s.substring(i + 1, j - 1) + opener); i = j; continue; } } else if (Character.isJavaIdentifierStart(c)) // for things like "this one's" do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); else if (Character.isDigit(c)) do ++j; while (j < l && Character.isDigit(s.charAt(j))); else if (cc.equals("[[")) { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (cc.equals("[=") && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else if (s.substring(j, Math.min(j + 3, l)).equals("...")) j += 3; else if (c == '$' || c == '#') do ++j; while (j < l && Character.isDigit(s.charAt(j))); else ++j; tok.add(s.substring(i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static boolean isIdentifier(String s) { return isJavaIdentifier(s); } static boolean isNonNegativeInteger(String s) { int n = l(s); if (n == 0) return false; int i = 0; while (i < n) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static boolean structure_showTiming, structure_checkTokenCount; static String structure(Object o) { return structure(o, new structure_Data()); } static String structure(Object o, structure_Data d) { StringWriter sw = new StringWriter(); d.out = new PrintWriter(sw); structure_go(o, d); String s = str(sw); if (structure_checkTokenCount) { print("token count=" + d.n); assertEquals("token count", l(javaTokC(s)), d.n); } return s; } static void structure_go(Object o, structure_Data d) { structure_1(o, d); while (nempty(d.stack)) popLast(d.stack).run(); } static void structureToPrintWriter(Object o, PrintWriter out) { structureToPrintWriter(o, out, new structure_Data()); } static void structureToPrintWriter(Object o, PrintWriter out, structure_Data d) { d.out = out; structure_go(o, d); } // leave to false, unless unstructure() breaks static boolean structure_allowShortening = false; // info on how to serialize objects of a certain class static class structure_ClassInfo { Class c; List fields; Method customSerializer; // can be set by caller of structure function IVF1 serializeObject; boolean special, nullInstances; } static class structure_Data { PrintWriter out; int stringSizeLimit; int shareStringsLongerThan = 20; boolean noStringSharing = false; boolean storeBaseClasses = false; String mcDollar = actualMCDollar(); IdentityHashMap seen = new IdentityHashMap(); // new BitSet refd; HashMap strings = new HashMap(); HashSet concepts = new HashSet(); HashMap infoByClass = new HashMap(); HashMap persistenceInfo = new HashMap(); // token count int n; List stack = new ArrayList(); // append single token structure_Data append(String token) { out.print(token); ++n; return this; } structure_Data append(int i) { out.print(i); ++n; return this; } // append multiple tokens structure_Data append(String token, int tokCount) { out.print(token); n += tokCount; return this; } // extend last token structure_Data app(String token) { out.print(token); return this; } structure_Data app(int i) { out.print(i); return this; } // called when a new class is detected // can be overridden by clients structure_ClassInfo newClass(Class c) { structure_ClassInfo info = new structure_ClassInfo(); info.c = c; infoByClass.put(c, info); if ((info.customSerializer = findMethodNamed(c, "_serialize")) != null) info.special = true; if (storeBaseClasses) { Class sup = c.getSuperclass(); if (sup != Object.class) { append("bc "); append(shortClassName(c)); out.print(" "); append(shortClassName(sup)); out.print(" "); } } return info; } void setFields(structure_ClassInfo info, List fields) { info.fields = fields; } } static void structure_1(final Object o, final structure_Data d) { try { if (o == null) { d.append("null"); return; } Class c = o.getClass(); boolean concept = false; concept = o instanceof Concept; structure_ClassInfo info = d.infoByClass.get(c); if (info == null) info = d.newClass(c); List lFields = info.fields; if (lFields == null) { // these are never back-referenced (for readability) if (o instanceof Number) { PrintWriter out = d.out; if (o instanceof Integer) { int i = ((Integer) o).intValue(); out.print(i); d.n += i < 0 ? 2 : 1; return; } if (o instanceof Long) { long l = ((Long) o).longValue(); out.print(l); out.print("L"); d.n += l < 0 ? 2 : 1; return; } if (o instanceof Short) { short s = ((Short) o).shortValue(); d.append("sh "); out.print(s); d.n += s < 0 ? 2 : 1; return; } if (o instanceof Float) { d.append("fl ", 2); quoteToPrintWriter(str(o), out); return; } if (o instanceof Double) { d.append("d(", 3); quoteToPrintWriter(str(o), out); d.append(")"); return; } if (o instanceof BigInteger) { out.print("bigint("); out.print(o); out.print(")"); d.n += ((BigInteger) o).signum() < 0 ? 5 : 4; return; } } if (o instanceof Boolean) { d.append(((Boolean) o).booleanValue() ? "t" : "f"); return; } if (o instanceof Character) { d.append(quoteCharacter((Character) o)); return; } if (o instanceof File) { d.append("File ").append(quote(((File) o).getPath())); return; } // referencable objects follow Integer ref = d.seen.get(o); if (o instanceof String && ref == null) ref = d.strings.get((String) o); if (ref != null) { /*d.refd.set(ref);*/ d.append("t").app(ref); return; } if (!(o instanceof String)) // record token number d.seen.put(o, d.n); else { String s = d.stringSizeLimit != 0 ? shorten((String) o, d.stringSizeLimit) : (String) o; if (!d.noStringSharing) { if (d.shareStringsLongerThan == Integer.MAX_VALUE) d.seen.put(o, d.n); if (l(s) >= d.shareStringsLongerThan) d.strings.put(s, d.n); } quoteToPrintWriter(s, d.out); d.n++; return; } if (o instanceof Set) { /*O set2 = unwrapSynchronizedSet(o); if (set2 != o) { d.append("sync"); o = set2; } TODO */ if (((Set) o) instanceof TreeSet) { d.append(isCISet_gen(((Set) o)) ? "ciset" : "treeset"); structure_1(new ArrayList(((Set) o)), d); return; } // assume it's a HashSet or LinkedHashSet d.append(((Set) o) instanceof LinkedHashSet ? "lhs" : "hashset"); structure_1(new ArrayList(((Set) o)), d); return; } String name = c.getName(); if (o instanceof Collection && !isJavaXClassName(name)) /* && neq(name, "main$Concept$RefL") */ { // it's a list if (name.equals("java.util.Collections$SynchronizedList") || name.equals("java.util.Collections$SynchronizedRandomAccessList")) { d.append("sync "); { structure_1(unwrapSynchronizedList(((List) o)), d); return; } } else if (name.equals("java.util.LinkedList")) d.append("ll"); d.append("["); final int l = d.n; final Iterator it = ((Collection) o).iterator(); d.stack.add(new Runnable() { public void run() { try { if (!it.hasNext()) d.append("]"); else { d.stack.add(this); if (d.n != l) d.append(", "); structure_1(it.next(), d); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!it.hasNext())\r\n d.append(\"]\");\r\n else {\r\n d.sta..."; } }); return; } if (o instanceof SynchronizedMap) { d.append("sync "); { structure_1(((SynchronizedMap) o).m, d); return; } } if (o instanceof Map && !startsWith(name, d.mcDollar)) { if (o instanceof LinkedHashMap) d.append("lhm"); else if (o instanceof HashMap) d.append("hm"); else if (o instanceof TreeMap) d.append(isCIMap_gen(((TreeMap) o)) ? "cimap" : "tm"); else if (name.equals("java.util.Collections$SynchronizedMap") || name.equals("java.util.Collections$SynchronizedSortedMap") || name.equals("java.util.Collections$SynchronizedNavigableMap")) { d.append("sync "); { structure_1(unwrapSynchronizedMap(((Map) o)), d); return; } } d.append("{"); final int l = d.n; final Iterator it = ((Map) o).entrySet().iterator(); d.stack.add(new Runnable() { boolean v = false; Map.Entry e; public void run() { if (v) { d.append("="); v = false; d.stack.add(this); structure_1(e.getValue(), d); } else { if (!it.hasNext()) d.append("}"); else { e = (Map.Entry) it.next(); v = true; d.stack.add(this); if (d.n != l) d.append(", "); structure_1(e.getKey(), d); } } } }); return; } if (c.isArray()) { if (o instanceof byte[]) { d.append("ba ").append(quote(bytesToHex((byte[]) o))); return; } final int n = Array.getLength(o); if (o instanceof boolean[]) { String hex = boolArrayToHex((boolean[]) o); int i = l(hex); while (i > 0 && hex.charAt(i - 1) == '0' && hex.charAt(i - 2) == '0') i -= 2; d.append("boolarray ").append(n).app(" ").append(quote(substring(hex, 0, i))); return; } // sep is not used yet String atype = "array"; if (o instanceof int[]) { // ret "intarray " + quote(intArrayToHex((int[]) o)); atype = "intarray"; // sep = " "; } else if (o instanceof double[]) { atype = "dblarray"; // sep = " "; } else { Pair p = arrayTypeAndDimensions(c); if (p.a == int.class) atype = "intarray"; else if (p.a == byte.class) atype = "bytearray"; else if (p.a == boolean.class) atype = "boolarray"; else if (p.a == double.class) atype = "dblarray"; else if (p.a == String.class) { atype = "array S"; d.n++; } else // fail("Unsupported array type: " + p.a); atype = "array"; if (p.b > 1) { // add number of dimensions atype += "/" + p.b; // 2 additional tokens will be written d.n += 2; } } d.append(atype).append("{"); d.stack.add(new Runnable() { int i; public void run() { if (i >= n) d.append("}"); else { d.stack.add(this); if (i > 0) d.append(", "); structure_1(Array.get(o, i++), d); } } }); return; } if (o instanceof Class) { d.append("class(", 2).append(quote(((Class) o).getName())).append(")"); return; } if (o instanceof Throwable) { d.append("exception(", 2).append(quote(((Throwable) o).getMessage())).append(")"); return; } if (o instanceof BitSet) { BitSet bs = (BitSet) o; d.append("bitset{", 2); int l = d.n; for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) { if (d.n != l) d.append(", "); d.append(i); } d.append("}"); return; } // Need more cases? This should cover all library classes... if (name.startsWith("java.") || name.startsWith("javax.")) { // Hm. this is not unstructure-able d.append("j ").append(quote(str(o))); // Hm. this is not unstructure-able return; } /*if (name.equals("main$Lisp")) { fail("lisp not supported right now"); }*/ if (info.special) { if (info.customSerializer != null) { // custom serialization (_serialize method) Object o2 = invokeMethod(info.customSerializer, o); d.append("cu "); String shortName = dropPrefix(d.mcDollar, name); d.append(shortName); d.out.append(' '); structure_1(o2, d); return; } else if (info.nullInstances) { d.append("null"); return; } else if (info.serializeObject != null) { info.serializeObject.get(o); return; } else throw fail("unknown special type"); } String dynName = shortDynamicClassName(o); if (concept && !d.concepts.contains(dynName)) { d.concepts.add(dynName); d.append("c "); } // serialize an object with fields. // first, collect all fields and values in fv. TreeSet fields = new TreeSet(new Comparator() { public int compare(Field a, Field b) { return stdcompare(a.getName(), b.getName()); } }); Class cc = c; while (cc != Object.class) { for (Field field : getDeclaredFields_cached(cc)) { String fieldName = field.getName(); if (fieldName.equals("_persistenceInfo")) d.persistenceInfo.put(c, field); if ((field.getModifiers() & (java.lang.reflect.Modifier.STATIC | java.lang.reflect.Modifier.TRANSIENT)) != 0) continue; fields.add(field); // put special cases here...? } cc = cc.getSuperclass(); } // TODO: S fieldOrder = getOpt(c, "_fieldOrder"); lFields = asList(fields); // Render this$0/this$1 first because unstructure needs it for constructor call. int n = l(lFields); for (int i = 0; i < n; i++) { Field f = lFields.get(i); if (f.getName().startsWith("this$")) { lFields.remove(i); lFields.add(0, f); break; } } d.setFields(info, lFields); } else // << if (lFields == null) { // ref handling for lFields != null Integer ref = d.seen.get(o); if (ref != null) { /*d.refd.set(ref);*/ d.append("t").app(ref); return; } // record token number d.seen.put(o, d.n); } Field persistenceInfoField = (Field) (d.persistenceInfo.get(c)); Map persistenceInfo = persistenceInfoField == null ? null : (Map) persistenceInfoField.get(o); LinkedHashMap fv = new LinkedHashMap(); for (Field f : lFields) { Object value; try { value = f.get(o); } catch (Exception e) { value = "?"; } if (value != null && (persistenceInfo == null || !Boolean.FALSE.equals(persistenceInfo.get(f.getName())))) fv.put(f.getName(), value); } String name = c.getName(); String shortName = dropPrefix("loadableUtils.utils$", dropPrefix(d.mcDollar, name)); // for anonymous classes if (startsWithDigit(shortName)) shortName = name; // Now we have fields & values. Process fieldValues if it's a DynamicObject. // omit field "className" if equal to class's name if (concept && eq(fv.get("className"), shortName)) fv.remove("className"); if (o instanceof DynamicObject) { putAll(fv, (Map) fv.get("fieldValues")); fv.remove("fieldValues"); shortName = shortDynamicClassName(o); fv.remove("className"); } String singleField = fv.size() == 1 ? first(fv.keySet()) : null; d.append(shortName); // correct token count d.n += countDots(shortName) * 2; final int l = d.n; final Iterator it = fv.entrySet().iterator(); d.stack.add(new Runnable() { public void run() { try { if (!it.hasNext()) { if (d.n != l) d.append(")"); } else { Map.Entry e = (Map.Entry) it.next(); d.append(d.n == l ? "(" : ", "); d.append((String) e.getKey()).append("="); d.stack.add(this); structure_1(e.getValue(), d); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (!it.hasNext()) {\r\n if (d.n != l)\r\n d.append(\")\");\r\n } else..."; } }); } catch (Exception __e) { throw rethrow(__e); } } static boolean isInteger(String s) { int n = l(s); if (n == 0) return false; int i = 0; if (s.charAt(0) == '-') if (++i >= n) return false; while (i < n) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static DialogIO talkToSubBot(final long vport, final DialogIO io) { return talkToSubBot(String.valueOf(vport), io); } static DialogIO talkToSubBot(final String subBot, final DialogIO io) { if (subBot == null) return io; return new talkToSubBot_IO(subBot, io); } static class talkToSubBot_IO extends DialogIO { String subBot; DialogIO io; talkToSubBot_IO(String subBot, DialogIO io) { this.io = io; this.subBot = subBot; } // delegate all but sendLine boolean isStillConnected() { return io.isStillConnected(); } String readLineImpl() { return io.readLineImpl(); } boolean isLocalConnection() { return io.isLocalConnection(); } Socket getSocket() { return io.getSocket(); } public void close() { try { io.close(); } catch (Exception __e) { throw rethrow(__e); } } void sendLine(String line) { io.sendLine(format3("please forward to bot *: *", subBot, line)); } } // works on lists and strings and null static int indexOfIgnoreCase(List a, String b) { return indexOfIgnoreCase(a, b, 0); } static int indexOfIgnoreCase(List a, String b, int i) { int n = a == null ? 0 : a.size(); for (; i < n; i++) if (eqic(a.get(i), b)) return i; return -1; } static int indexOfIgnoreCase(String a, String b) { return indexOfIgnoreCase_manual(a, b); /*Matcher m = Pattern.compile(b, Pattern.CASE_INSENSITIVE + Pattern.LITERAL).matcher(a); if (m.find()) return m.start(); else ret -1;*/ } static int indexOfIgnoreCase(String a, String b, int i) { return indexOfIgnoreCase_manual(a, b, i); } static List quickBotScan() { return ProgramScan.quickBotScan(); } static List quickBotScan(int[] preferredPorts) { return ProgramScan.quickBotScan(preferredPorts); } static List quickBotScan(String searchPattern) { List l = new ArrayList(); for (ProgramScan.Program p : ProgramScan.quickBotScan()) if (indexOfIgnoreCase(p.helloString, searchPattern) == 0) l.add(p); return l; } static String firstPartOfHelloString(String s) { int i = s.lastIndexOf('/'); return i < 0 ? s : rtrim(s.substring(0, i)); } // TODO: cyclic structures involving certain lists & sets static Object unstructure(String text) { return unstructure(text, false); } static Object unstructure(String text, boolean allDynamic) { return unstructure(text, allDynamic, null); } static Object unstructure(String text, IF1 classFinder) { return unstructure(text, false, classFinder); } static int structure_internStringsLongerThan = 50; static int unstructure_unquoteBufSize = 100; // stats static int unstructure_tokrefs; abstract static class unstructure_Receiver { abstract void set(Object o); } // classFinder: func(name) -> class (optional) static Object unstructure(String text, boolean allDynamic, Object classFinder) { if (text == null) return null; return unstructure_tok(javaTokC_noMLS_iterator(text), allDynamic, classFinder); } static Object unstructure_reader(BufferedReader reader) { return unstructure_tok(javaTokC_noMLS_onReader(reader), false, null); } static Object unstructure_tok(final Producer tok, final boolean allDynamic, final Object _classFinder) { final boolean debug = unstructure_debug; final class X { int i = -1; final Object classFinder = _classFinder != null ? _classFinder : _defaultClassFinder(); String mcDollar = actualMCDollar(); HashMap refs = new HashMap(); HashMap tokrefs = new HashMap(); HashSet concepts = new HashSet(); HashMap classesMap = new HashMap(); List stack = new ArrayList(); Map baseClassMap = new HashMap(); HashMap innerClassConstructors = new HashMap(); String curT; char[] unquoteBuf = new char[unstructure_unquoteBufSize]; X() { try { Class mc = (Class) (callF(_classFinder, "
")); if (mc != null) mcDollar = mc.getName() + "$"; } catch (Throwable __e) { _handleException(__e); } } Class findAClass(String fullClassName) { return classFinder != null ? (Class) callF(classFinder, fullClassName) : findClass_fullName(fullClassName); } String unquote(String s) { return unquoteUsingCharArray(s, unquoteBuf); } // look at current token String t() { return curT; } // get current token, move to next String tpp() { String t = curT; consume(); return t; } void parse(final unstructure_Receiver out) { String t = t(); int refID; if (structure_isMarker(t, 0, l(t))) { refID = parseInt(t.substring(1)); consume(); } else refID = -1; // if (debug) print("parse: " + quote(t)); final int tokIndex = i; parse_inner(refID, tokIndex, new unstructure_Receiver() { void set(Object o) { if (refID >= 0) refs.put(refID, o); if (o != null) tokrefs.put(tokIndex, o); out.set(o); } }); } void parse_inner(int refID, int tokIndex, unstructure_Receiver out) { String t = t(); // if (debug) print("parse_inner: " + quote(t)); Class c = classesMap.get(t); if (c == null) { if (t.startsWith("\"")) { String s = internIfLongerThan(unquote(tpp()), structure_internStringsLongerThan); out.set(s); return; } if (t.startsWith("'")) { out.set(unquoteCharacter(tpp())); return; } if (t.equals("bigint")) { out.set(parseBigInt()); return; } if (t.equals("d")) { out.set(parseDouble()); return; } if (t.equals("fl")) { out.set(parseFloat()); return; } if (t.equals("sh")) { consume(); t = tpp(); if (t.equals("-")) { t = tpp(); out.set((short) (-parseInt(t))); return; } out.set((short) parseInt(t)); return; } if (t.equals("-")) { consume(); t = tpp(); out.set(isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t))); return; } if (isInteger(t) || isLongConstant(t)) { consume(); // if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t)); if (isLongConstant(t)) { out.set(parseLong(t)); return; } long l = parseLong(t); boolean isInt = l == (int) l; out.set(isInt ? (Object) Integer.valueOf((int) l) : (Object) Long.valueOf(l)); return; } if (t.equals("false") || t.equals("f")) { consume(); out.set(false); return; } if (t.equals("true") || t.equals("t")) { consume(); out.set(true); return; } if (t.equals("-")) { consume(); t = tpp(); out.set(isLongConstant(t) ? (Object) (-parseLong(t)) : (Object) (-parseInt(t))); return; } if (isInteger(t) || isLongConstant(t)) { consume(); // if (debug) print("isLongConstant " + quote(t) + " => " + isLongConstant(t)); if (isLongConstant(t)) { out.set(parseLong(t)); return; } long l = parseLong(t); boolean isInt = l == (int) l; out.set(isInt ? (Object) Integer.valueOf((int) l) : (Object) Long.valueOf(l)); return; } if (t.equals("File")) { consume(); File f = new File(unquote(tpp())); out.set(f); return; } if (t.startsWith("r") && isInteger(t.substring(1))) { consume(); int ref = Integer.parseInt(t.substring(1)); Object o = refs.get(ref); if (o == null) throw fail("unsatisfied back reference " + ref); out.set(o); return; } if (t.startsWith("t") && isInteger(t.substring(1))) { consume(); int ref = Integer.parseInt(t.substring(1)); Object o = tokrefs.get(ref); if (o == null) throw fail("unsatisfied token reference " + ref + " at " + tokIndex); out.set(o); return; } if (t.equals("hashset")) { parseHashSet(out); return; } if (t.equals("lhs")) { parseLinkedHashSet(out); return; } if (t.equals("treeset")) { parseTreeSet(out); return; } if (t.equals("ciset")) { parseCISet(out); return; } if (eqOneOf(t, "hashmap", "hm")) { consume(); parseMap(new HashMap(), out); return; } if (t.equals("lhm")) { consume(); parseMap(new LinkedHashMap(), out); return; } if (t.equals("tm")) { consume(); parseMap(new TreeMap(), out); return; } if (t.equals("cimap")) { consume(); parseMap(ciMap(), out); return; } if (t.equals("ll")) { consume(); LinkedList l = new LinkedList(); if (refID >= 0) refs.put(refID, l); { parseList(l, out); return; } } if (t.equals("syncLL")) { // legacy consume(); { parseList(synchroLinkedList(), out); return; } } if (t.equals("sync")) { consume(); { parse(new unstructure_Receiver() { void set(Object value) { if (value instanceof Map) { // Java 7 if (value instanceof NavigableMap) { out.set(synchroNavigableMap(((NavigableMap) value))); return; } if (value instanceof SortedMap) { out.set(synchroSortedMap(((SortedMap) value))); return; } { out.set(synchroMap((Map) value)); return; } } else { out.set(synchroList((List) value)); return; } } }); return; } } if (t.equals("{")) { parseMap(out); return; } if (t.equals("[")) { ArrayList l = new ArrayList(); if (refID >= 0) refs.put(refID, l); this.parseList(l, out); return; } if (t.equals("bitset")) { parseBitSet(out); return; } if (t.equals("array") || t.equals("intarray") || t.equals("dblarray")) { parseArray(out); return; } if (t.equals("ba")) { consume(); String hex = unquote(tpp()); out.set(hexToBytes(hex)); return; } if (t.equals("boolarray")) { consume(); int n = parseInt(tpp()); String hex = unquote(tpp()); out.set(boolArrayFromBytes(hexToBytes(hex), n)); return; } if (t.equals("class")) { out.set(parseClass()); return; } if (t.equals("l")) { parseLisp(out); return; } if (t.equals("null")) { consume(); out.set(null); return; } if (eq(t, "c")) { consume(); t = t(); assertTrue(isJavaIdentifier(t)); concepts.add(t); } // custom deserialization (new static method method) if (eq(t, "cu")) { consume(); t = tpp(); assertTrue(isJavaIdentifier(t)); String fullClassName = mcDollar + t; Class _c = findAClass(fullClassName); if (_c == null) throw fail("Class not found: " + fullClassName); parse(new unstructure_Receiver() { void set(Object value) { out.set(call(_c, "_deserialize", value)); } }); return; } } if (eq(t, "j")) { consume(); out.set(parseJava()); return; } if (eq(t, "bc")) { consume(); String c1 = tpp(); String c2 = tpp(); baseClassMap.put(c1, c2); { parse_inner(refID, i, out); return; } } // add more tokens here if (c == null && !isJavaIdentifier(t)) throw new RuntimeException("Unknown token " + (i + 1) + ": " + quote(t)); // any other class name (or package name) consume(); String className, fullClassName; // Is it a package name? if (eq(t(), ".")) { consume(); className = fullClassName = t + "." + assertIdentifier(tpp()); } else { className = t; fullClassName = mcDollar + t; } if (c == null && !allDynamic) { // First, find class c = findAClass(fullClassName); if (c != null) classesMap.put(className, c); } // check for existing base class if (c == null && !allDynamic) { String baseName = baseClassMap.get(className); if (baseName != null) { c = findAClass(mcDollar + baseName); printVars_str("Reverting to base class", "className", className, "baseName", baseName, "c", c); if (c != null) classesMap.put(className, c); } } // Check if it has an outer reference boolean hasBracket = eq(t(), "("); if (hasBracket) consume(); boolean hasOuter = hasBracket && startsWith(t(), "this$"); DynamicObject dO = null; Object o = null; final String thingName = t; if (c != null) { if (hasOuter) { try { Constructor ctor = innerClassConstructors.get(c); if (ctor == null) innerClassConstructors.put(c, ctor = nuStubInnerObject_findConstructor(c, classFinder)); o = ctor.newInstance(new Object[] { null }); } catch (Exception __e) { throw rethrow(__e); } } else o = nuEmptyObject(c); if (o instanceof DynamicObject) dO = (DynamicObject) o; } else { if (concepts.contains(t) && (c = findAClass(mcDollar + "Concept")) != null) o = dO = (DynamicObject) nuEmptyObject(c); else dO = new DynamicObject(); dO.className = className; } // Save in references list early because contents of object // might link back to main object if (refID >= 0) refs.put(refID, o != null ? o : dO); tokrefs.put(tokIndex, o != null ? o : dO); // NOW parse the fields! // no longer preserving order (why did we do this?) HashMap fields = new HashMap(); Object _o = o; DynamicObject _dO = dO; if (hasBracket) { stack.add(new Runnable() { public void run() { try { if (eq(t(), ",")) consume(); if (eq(t(), ")")) { consume(")"); objRead(_o, _dO, fields, hasOuter); out.set(_o != null ? _o : _dO); } else { final String key = unquote(tpp()); String t = tpp(); if (!eq(t, "=")) throw fail("= expected, got " + t + " after " + quote(key) + " in object " + thingName); stack.add(this); parse(new unstructure_Receiver() { void set(Object value) { fields.put(key, value); /*ifdef unstructure_debug print("Got field value " + value + ", next token: " + t()); endifdef*/ // if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ifdef unstructure_debug\r\n print(\"in object values, token: \" + t())..."; } }); } else { objRead(o, dO, fields, hasOuter); out.set(o != null ? o : dO); } } void objRead(Object o, DynamicObject dO, Map fields, boolean hasOuter) { // translate between diferent compilers (this$0 vs this$1) Object outer = fields.get("this$0"); if (outer != null) fields.put("this$1", outer); else { outer = fields.get("this$1"); if (outer != null) fields.put("this$0", outer); } if (o != null) { if (dO != null) { setOptAllDyn_pcall(dO, fields); } else { setOptAll_pcall(o, fields); } if (hasOuter) fixOuterRefs(o); } else for (Map.Entry e : fields.entrySet()) setDynObjectValue(dO, intern(e.getKey()), e.getValue()); if (o != null) pcallOpt_noArgs(o, "_doneLoading"); } void parseSet(final Set set, final unstructure_Receiver out) { this.parseList(new ArrayList(), new unstructure_Receiver() { void set(Object o) { set.addAll((List) o); out.set(set); } }); } void parseLisp(final unstructure_Receiver out) { throw fail("class Lisp not included"); } void parseBitSet(final unstructure_Receiver out) { consume("bitset"); consume("{"); final BitSet bs = new BitSet(); stack.add(new Runnable() { public void run() { try { if (eq(t(), "}")) { consume("}"); out.set(bs); } else { stack.add(this); parse(new unstructure_Receiver() { void set(Object o) { bs.set((Integer) o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"}\")) {\r\n consume(\"}\");\r\n out.set(bs);\r\n ..."; } }); } void parseList(final List list, final unstructure_Receiver out) { tokrefs.put(i, list); consume("["); stack.add(new Runnable() { public void run() { try { if (eq(t(), "]")) { consume(); out.set(list); } else { stack.add(this); parse(new unstructure_Receiver() { void set(Object o) { // if (debug) print("List element type: " + getClassName(o)); list.add(o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"]\")) {\r\n consume();\r\n ifdef unstructure_debug\r..."; } }); } void parseArray(unstructure_Receiver out) { String _type = tpp(); int dims; if (eq(t(), "S")) { // string array _type = "S"; consume(); } if (eq(t(), "/")) { // multi-dimensional array consume(); dims = parseInt(tpp()); } else dims = 1; consume("{"); List list = new ArrayList(); String type = _type; stack.add(new Runnable() { public void run() { try { if (eq(t(), "}")) { consume("}"); if (dims > 1) { Class atype; if (type.equals("intarray")) atype = int.class; else if (type.equals("S")) atype = String.class; else throw todo("multi-dimensional arrays of other types"); out.set(list.toArray((Object[]) newMultiDimensionalOuterArray(atype, dims, l(list)))); } else out.set(type.equals("intarray") ? toIntArray(list) : type.equals("dblarray") ? toDoubleArray(list) : type.equals("S") ? toStringArray(list) : list.toArray()); } else { stack.add(this); parse(new unstructure_Receiver() { void set(Object o) { list.add(o); if (eq(t(), ",")) consume(); } }); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (eq(t(), \"}\")) {\r\n consume(\"}\");\r\n if (dims > 1) {\r\n ..."; } }); } Object parseClass() { consume("class"); consume("("); String name = unquote(tpp()); consume(")"); Class c = allDynamic ? null : findAClass(name); if (c != null) return c; DynamicObject dO = new DynamicObject(); dO.className = "java.lang.Class"; name = dropPrefix(mcDollar, name); dO.fieldValues.put("name", name); return dO; } Object parseBigInt() { consume("bigint"); consume("("); String val = tpp(); if (eq(val, "-")) val = "-" + tpp(); consume(")"); return new BigInteger(val); } Object parseDouble() { consume("d"); consume("("); String val = unquote(tpp()); consume(")"); return Double.parseDouble(val); } Object parseFloat() { consume("fl"); String val; if (eq(t(), "(")) { consume("("); val = unquote(tpp()); consume(")"); } else { val = unquote(tpp()); } return Float.parseFloat(val); } void parseHashSet(unstructure_Receiver out) { consume("hashset"); parseSet(new HashSet(), out); } void parseLinkedHashSet(unstructure_Receiver out) { consume("lhs"); parseSet(new LinkedHashSet(), out); } void parseTreeSet(unstructure_Receiver out) { consume("treeset"); parseSet(new TreeSet(), out); } void parseCISet(unstructure_Receiver out) { consume("ciset"); parseSet(ciSet(), out); } void parseMap(unstructure_Receiver out) { parseMap(new TreeMap(), out); } Object parseJava() { String j = unquote(tpp()); Matches m = new Matches(); if (jmatch("java.awt.Color[r=*,g=*,b=*]", j, m)) return nuObject("java.awt.Color", parseInt(m.unq(0)), parseInt(m.unq(1)), parseInt(m.unq(2))); else { warn("Unknown Java object: " + j); return null; } } void parseMap(final Map map, final unstructure_Receiver out) { consume("{"); stack.add(new Runnable() { boolean v = false; Object key; public void run() { if (v) { v = false; stack.add(this); if (!eq(tpp(), "=")) throw fail("= expected, got " + t() + " in map of size " + l(map)); parse(new unstructure_Receiver() { void set(Object value) { map.put(key, value); if (eq(t(), ",")) consume(); } }); } else { if (eq(t(), "}")) { consume("}"); out.set(map); } else { v = true; stack.add(this); parse(new unstructure_Receiver() { void set(Object o) { key = o; } }); } } // if v else } }); } /*void parseSub(unstructure_Receiver out) { int n = l(stack); parse(out); while (l(stack) > n) stack }*/ void consume() { curT = tok.next(); ++i; } void consume(String s) { if (!eq(t(), s)) { /*S prevToken = i-1 >= 0 ? tok.get(i-1) : ""; S nextTokens = join(tok.subList(i, Math.min(i+2, tok.size()))); fail(quote(s) + " expected: " + prevToken + " " + nextTokens + " (" + i + "/" + tok.size() + ")");*/ throw fail(quote(s) + " expected, got " + quote(t())); } consume(); } // outer wrapper function getting first token and unwinding the stack void parse_initial(unstructure_Receiver out) { // get first token consume(); parse(out); while (nempty(stack)) popLast(stack).run(); } } ThreadLocal tlLoading = dynamicObjectIsLoading_threadLocal(); Boolean b = tlLoading.get(); tlLoading.set(true); try { final Var v = new Var(); X x = new X(); x.parse_initial(new unstructure_Receiver() { void set(Object o) { v.set(o); } }); unstructure_tokrefs = x.tokrefs.size(); return v.get(); } finally { tlLoading.set(b); } } static boolean unstructure_debug = false; static String sendToLocalBotQuietly(String bot, String text, Object... args) { text = format3(text, args); DialogIO channel = newFindBot2(bot); try { if (channel == null) throw fail(quote(bot) + " not found"); try { channel.readLine(); channel.sendLine(text); String s = channel.readLine(); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } static String sendToLocalBotQuietly(int port, String text, Object... args) { text = format3(text, args); DialogIO channel = talkTo(port); try { try { channel.readLine(); channel.sendLine(text); String s = channel.readLine(); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } static boolean isLocalhost(String ip) { return isLoopbackIP(ip) || eqic(ip, "localhost"); } static int vmPort() { return myVMPort(); } static DialogIO talkToThisVM() { return new talkToThisVM_IO(); } static class talkToThisVM_IO extends DialogIO { List answers = ll(thisVMGreeting()); boolean isLocalConnection() { return true; } boolean isStillConnected() { return true; } int getPort() { return vmPort(); } void sendLine(String line) { answers.add(or2(sendToThisVM_newThread(line), "?")); } String readLineImpl() { try { return popFirst(answers); } catch (Exception __e) { throw rethrow(__e); } } public void close() { } Socket getSocket() { return null; } } static long parseLong(String s) { if (empty(s)) return 0; return Long.parseLong(dropSuffix("L", s)); } static long parseLong(Object s) { return Long.parseLong((String) s); } static File localSnippetsDir() { return javaxDataDir("Personal Programs"); } static File localSnippetsDir(String sub) { return newFile(localSnippetsDir(), sub); } static File oneOfTheFiles(String... paths) { if (paths != null) for (String path : paths) if (fileExists(path)) return newFile(path); return null; } static File oneOfTheFiles(File... files) { return oneOfTheFiles(asList(files)); } static File oneOfTheFiles(Iterable files) { if (files != null) for (File f : files) if (fileExists(f)) return f; return null; } // can be set to work on different base dir static File javaxSecretDir_dir; static File javaxSecretDir() { return javaxSecretDir_dir != null ? javaxSecretDir_dir : new File(userHome(), "JavaX-Secret"); } static File javaxSecretDir(String sub) { return newFile(javaxSecretDir(), sub); } // func(S, O[]) -> bool static volatile Object isAllowed_function; static volatile boolean isAllowed_all = true; static boolean isAllowed(String askingMethod, Object... args) { // check on VM level Object f = vm_generalMap_get("isAllowed_function"); if (f != null && !isTrue(callF(f, askingMethod, args))) return false; // check locally return isAllowed_all || isTrue(callF(isAllowed_function, askingMethod, args)); } static String baseClassName(String className) { return substring(className, className.lastIndexOf('.') + 1); } static String baseClassName(Object o) { return baseClassName(getClassName(o)); } static String prependIfNempty(String prefix, String s) { return empty(s) ? unnull(s) : prefix + s; } static long round(double d) { return Math.round(d); } static String round(String s) { return roundBracket(s); } static String hmsWithColons() { return hmsWithColons(now()); } static String hmsWithColons(long time) { return new SimpleDateFormat("HH:mm:ss").format(time); } static String getComputerID_quick() { return computerID(); } static String joinNemptiesWithColonSpace(String... strings) { return joinNempties(": ", strings); } static String joinNemptiesWithColonSpace(Collection strings) { return joinNempties(": ", strings); } static String tryToReadErrorStreamFromURLConnection(URLConnection conn) { try { if (conn instanceof HttpURLConnection) // TODO: ensure some max length return stream2string(((HttpURLConnection) conn).getErrorStream()); return null; } catch (Throwable __e) { return null; } } static int gzInputStream_defaultBufferSize = 65536; static GZIPInputStream gzInputStream(File f) { try { return gzInputStream(new FileInputStream(f)); } catch (Exception __e) { throw rethrow(__e); } } static GZIPInputStream gzInputStream(File f, int bufferSize) { try { return gzInputStream(new FileInputStream(f), bufferSize); } catch (Exception __e) { throw rethrow(__e); } } static GZIPInputStream gzInputStream(InputStream in) { return gzInputStream(in, gzInputStream_defaultBufferSize); } static GZIPInputStream gzInputStream(InputStream in, int bufferSize) { try { return _registerIOWrap(new GZIPInputStream(in, gzInputStream_defaultBufferSize), in); } catch (Exception __e) { throw rethrow(__e); } } static boolean endsWith(String a, String b) { return a != null && a.endsWith(b); } static boolean endsWith(String a, char c) { return nempty(a) && lastChar(a) == c; } static boolean endsWith(String a, String b, Matches m) { if (!endsWith(a, b)) return false; m.m = new String[] { dropLast(l(b), a) }; return true; } static Map compileRegexp_cache = syncMRUCache(10); static java.util.regex.Pattern compileRegexp(String pat) { java.util.regex.Pattern p = compileRegexp_cache.get(pat); if (p == null) { compileRegexp_cache.put(pat, p = java.util.regex.Pattern.compile(pat)); } return p; } static String getProgramTitle() { return getProgramName(); } static JTextArea jTextArea() { return jTextArea(""); } static JTextArea jTextArea(final String text) { return jTextAreaWithUndo(text); } static B mapPutOrRemove(Map map, A key, B value) { if (map != null && key != null) if (value != null) return map.put(key, value); else return map.remove(key); return null; } static String intToHex_flexLength(int i) { return Integer.toHexString(i); } // first delay = delay static Timer installTimer(JComponent component, Object r, long delay) { return installTimer(component, r, delay, delay); } // first delay = delay static Timer installTimer(RootPaneContainer frame, long delay, Object r) { return installTimer(frame.getRootPane(), r, delay, delay); } // first delay = delay static Timer installTimer(JComponent component, long delay, Object r) { return installTimer(component, r, delay, delay); } static Timer installTimer(JComponent component, long delay, long firstDelay, Object r) { return installTimer(component, r, delay, firstDelay); } static Timer installTimer(final JComponent component, final Object r, final long delay, final long firstDelay) { return installTimer(component, r, delay, firstDelay, true); } static Timer installTimer(final JComponent component, final Object r, final long delay, final long firstDelay, final boolean repeats) { if (component == null) return null; return (Timer) swingAndWait(new F0() { public Object get() { try { final Var timer = new Var(); timer.set(new Timer(toInt(delay), new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent _evt) { try { AutoCloseable __1 = tempActivity(r); try { try { if (!allPaused()) if (isFalse(callF(r))) cancelTimer(timer.get()); } catch (Throwable __e) { _handleException(__e); } } finally { _close(__1); } } catch (Throwable __e) { messageBox(__e); } } })); timer.get().setInitialDelay(toInt(firstDelay)); timer.get().setRepeats(repeats); bindTimerToComponent(timer.get(), component); return timer.get(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "final new Var timer;\r\n timer.set(new Timer(toInt(delay), actionList..."; } }); } static Timer installTimer(RootPaneContainer frame, long delay, long firstDelay, Object r) { return installTimer(frame.getRootPane(), delay, firstDelay, r); } static void listThreadLocalAdd(ThreadLocal> tl, A a) { List l = tl.get(); if (l == null) tl.set(l = new ArrayList()); l.add(a); } static A listThreadLocalPopLast(ThreadLocal> tl) { List l = tl.get(); if (l == null) return null; A a = popLast(l); if (empty(l)) tl.set(null); return a; } static Dimension getScreenSize() { return Toolkit.getDefaultToolkit().getScreenSize(); } static Object[] mapToParams(Map map) { return mapToObjectArray(map); } static Object[] unrollParams(Object[] params) { if (l(params) == 1 && params[0] instanceof Map) return mapToParams((Map) params[0]); return params; } static Object html_valueLessParam_cache; static Object html_valueLessParam() { if (html_valueLessParam_cache == null) html_valueLessParam_cache = html_valueLessParam_load(); return html_valueLessParam_cache; } static Object html_valueLessParam_load() { return new Object(); } static String htmlQuote(String s) { return "\"" + htmlencode_forParams(s) + "\""; } // TODO: process CDATA, scripts static List htmlcoarsetok(String s) { List tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0; while (i < l) { int j = i; char c; // scan for non-tags while (j < l) { if (s.charAt(j) != '<') // regular character ++j; else if (s.substring(j, Math.min(j + 4, l)).equals("")); j = Math.min(j + 3, l); } else { // character after < char d = charAt(s, j + 1); if (d == '/' || isLetter(d)) // it's a tag break; else ++j; } } // add non-tag content tok.add(s.substring(i, j)); i = j; if (i >= l) break; c = s.charAt(i); // scan over tag if (c == '<') { ++j; // TODO: strings in tag? while (j < l && s.charAt(j) != '>') ++j; if (j < l) ++j; } // add tag tok.add(s.substring(i, j)); i = j; } if ((tok.size() & 1) == 0) tok.add(""); return tok; } static boolean getHtmlTagParameters_debug = false; static Map getHtmlTagParameters(String tag) { if (empty(tag)) return null; List tok = codeTokens(tok_joinMinusIdentifiers(htmlFineTok(tag))); if (getHtmlTagParameters_debug) printStruct(tok); assertEquals("<", tok.get(0)); int i = 1; if (eq(tok.get(1), "/")) ++i; String name = tok.get(i++); if (!isMinusIdentifier(name)) throw fail(tag + " (" + name + ")"); Map map = new HashMap(); while (i < l(tok)) { String t = tok.get(i); if (eqOneOf(t, "/", ">")) break; if (!isMinusIdentifier(t)) throw fail(tag + " (" + t + ")"); ++i; String value = "1"; if (eq(tok.get(i), "=")) { ++i; value = htmlunquote(tok.get(i++)); } map.put(t, value); } return map; } static Map cloneMap(Map map) { if (map == null) return new HashMap(); // assume mutex is equal to map synchronized (map) { return // copies comparator map instanceof TreeMap ? // copies comparator new TreeMap((TreeMap) map) : map instanceof LinkedHashMap ? new LinkedHashMap(map) : new HashMap(map); } } static List cloneMap(Iterable l, IF1 f) { List x = emptyList(l); if (l != null) for (A o : cloneList(l)) x.add(f.get(o)); return x; } static boolean neqic(String a, String b) { return !eqic(a, b); } static boolean neqic(char a, char b) { return !eqic(a, b); } static A[] dropLast(A[] a) { return dropLast(a, 1); } static A[] dropLast(A[] a, int n) { if (a == null) return null; n = Math.min(n, a.length); A[] b = arrayOfSameType(a, a.length - n); System.arraycopy(a, 0, b, 0, b.length); return b; } static List dropLast(List l) { return subList(l, 0, l(l) - 1); } static List dropLast(int n, List l) { return subList(l, 0, l(l) - n); } static List dropLast(Iterable l) { return dropLast(asList(l)); } static String dropLast(String s) { return substring(s, 0, l(s) - 1); } static String dropLast(String s, int n) { return substring(s, 0, l(s) - n); } static String dropLast(int n, String s) { return dropLast(s, n); } static JPanel jFullCenter(final Component c) { return swing(new F0() { public JPanel get() { try { JPanel panel = new JPanel(new GridBagLayout()); panel.add(c); return panel; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "JPanel panel = new JPanel(new GridBagLayout);\r\n panel.add(c);\r\n ret panel;"; } }); } static TreeMap caseInsensitiveMap() { return new TreeMap(caseInsensitiveComparator()); } // f : Matcher -> S static String regexReplaceIC(String s, String pat, Object f) { return regexReplace(regexpMatcherIC(pat, s), f); } static String regexReplaceIC(String s, String pat, String replacement) { return regexpReplaceIC_direct(s, pat, replacement); } static List collectField(Iterable c, String field) { List l = new ArrayList(); if (c != null) for (Object a : c) l.add(getOpt(a, field)); return l; } static List collectField(String field, Iterable c) { return collectField(c, field); } static void logQuotedWithTime(String s) { logQuotedWithTime(standardLogFile(), s); } static void logQuotedWithTime(File logFile, String s) { logQuoted(logFile, logQuotedWithTime_format(s)); } static void logQuotedWithTime(String logFile, String s) { logQuoted(logFile, logQuotedWithTime_format(s)); } static String logQuotedWithTime_format(String s) { return /*formatGMTWithDate_24*/ (now()) + " " + s; } static A onClick(final A c, final Object runnable) { if (c != null) { swing(new Runnable() { public void run() { try { c.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { callF(runnable, e); } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "c.addMouseListener(new MouseAdapter {\r\n public void mouseClicked(MouseEv..."; } }); } return c; } // re-interpreted for buttons static void onClick(JButton btn, final Object runnable) { onEnter(btn, runnable); } static void disposeWindow(final Window window) { if (window != null) { swing(new Runnable() { public void run() { try { // call listeners window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); myFrames_list.remove(window); window.dispose(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "window.dispatchEvent(new WindowEvent(window, WindowEvent.WINDOW_CLOSING)); //..."; } }); } } static void disposeWindow(final Component c) { disposeWindow(getWindow(c)); } static void disposeWindow(Object o) { if (o != null) disposeWindow(((Component) o)); } static void disposeWindow() { disposeWindow(heldInstance(Component.class)); } static boolean vmBus_anyFalse(String msg, Object... args) { return contains(vmBus_queryAll(msg, args), false); } static File parentFile(File f) { return dirOfFile(f); } static BufferedReader bufferedReader(Reader r) { return bufferedReader(r, 8192); } static BufferedReader bufferedReader(Reader r, int bufSize) { if (r == null) return null; return r instanceof BufferedReader ? (BufferedReader) r : _registerIOWrap(new BufferedReader(r, bufSize), r); } static A holdResource(IResourceHolder holder, A a) { { if (holder != null) holder.add(a); } return a; } static CloseableIterableIterator iteratorFromFunction_f0_autoCloseable(final F0 f, final AutoCloseable closeable) { class IFF2 extends CloseableIterableIterator { A a; boolean done = false; public boolean hasNext() { getNext(); return !done; } public A next() { getNext(); if (done) throw fail(); A _a = a; a = null; return _a; } void getNext() { if (done || a != null) return; a = f.get(); done = a == null; } public void close() throws Exception { if (closeable != null) closeable.close(); } } ; return new IFF2(); } static String readLineFromReaderWithClose(BufferedReader r) { try { String s = r.readLine(); if (s == null) r.close(); return s; } catch (Exception __e) { throw rethrow(__e); } } static AutoCloseable _wrapIOCloseable(final AutoCloseable c) { return c == null ? null : new AutoCloseable() { public String toString() { return "c.close();\r\n _registerIO(c, null, false);"; } public void close() throws Exception { c.close(); _registerIO(c, null, false); } }; } static A _registerIOWrap(A wrapper, Object wrapped) { return wrapper; } static FileInputStream newFileInputStream(File path) throws IOException { return newFileInputStream(path.getPath()); } static FileInputStream newFileInputStream(String path) throws IOException { FileInputStream f = new FileInputStream(path); _registerIO(f, path, true); return f; } static boolean domainIsUnder(String domain, String mainDomain) { return eqic(domain, mainDomain) || ewic(domain, "." + mainDomain); } static String theAGIBlueDomain() { return "agi.blue"; } static List wrapAsReversedList(A[] array) { int n = l(array); return new RandomAccessAbstractList() { public int size() { return n; } public A get(int i) { return array[n - 1 - i]; } public A set(int i, A a) { A old = array[n - 1 - i]; array[n - 1 - i] = a; return old; } }; } static HashMap> callMC_cache = new HashMap(); static String callMC_key; static Method callMC_value; // varargs assignment fixer for a single string array argument static Object callMC(String method, String[] arg) { return callMC(method, new Object[] { arg }); } static Object callMC(String method, Object... args) { try { Method me; // initializer time workaround if (callMC_cache == null) callMC_cache = new HashMap(); synchronized (callMC_cache) { me = method == callMC_key ? callMC_value : null; } if (me != null) try { return invokeMethod(me, null, args); } catch (IllegalArgumentException e) { throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e); } List m; synchronized (callMC_cache) { m = callMC_cache.get(method); } if (m == null) { if (callMC_cache.isEmpty()) { callMC_makeCache(); m = callMC_cache.get(method); } if (m == null) throw fail("Method named " + method + " not found in main"); } int n = m.size(); if (n == 1) { me = m.get(0); synchronized (callMC_cache) { callMC_key = method; callMC_value = me; } try { return invokeMethod(me, null, args); } catch (IllegalArgumentException e) { throw new RuntimeException("Can't call " + me + " with arguments " + classNames(args), e); } } for (int i = 0; i < n; i++) { me = m.get(i); if (call_checkArgs(me, args, false)) return invokeMethod(me, null, args); } throw fail("No method called " + method + " with arguments (" + joinWithComma(getClasses(args)) + ") found in main"); } catch (Exception __e) { throw rethrow(__e); } } static void callMC_makeCache() { synchronized (callMC_cache) { callMC_cache.clear(); Class _c = (Class) mc(), c = _c; while (c != null) { for (Method m : c.getDeclaredMethods()) if ((m.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0) { makeAccessible(m); multiMapPut(callMC_cache, m.getName(), m); } c = c.getSuperclass(); } } } static List getClassNames(Collection l) { List out = new ArrayList(); if (l != null) for (Object o : l) out.add(o == null ? null : getClassName(o)); return out; } static Object[] dropEntryFromParams(Object[] params, int i) { int n = l(params); if (i < 0 || i >= n) return params; if (n == 2) return null; Object[] p = new Object[n - 2]; System.arraycopy(params, 0, p, 0, i); System.arraycopy(params, i + 2, p, i, n - i - 2); return p; } static List filterConcepts(List list, Object... params) { if (empty(params)) return list; List l = new ArrayList(); for (A x : list) if (checkConceptFields(x, params)) l.add(x); return l; } static Object _defaultClassFinder_value = defaultDefaultClassFinder(); static Object _defaultClassFinder() { return _defaultClassFinder_value; } static AutoCloseable tempRemove(Map map, A key) { if (map == null || !map.containsKey(key)) return null; B b = map.get(key); map.remove(key); return new AutoCloseable() { public String toString() { return "map.put(key, b);"; } public void close() throws Exception { map.put(key, b); } }; } static void duplicateThisProgram() { nohupJavax(trim(programID() + " " + smartJoin((String[]) get(getJavaX(), "fullArgs")))); } static Map weakHashMap() { return newWeakHashMap(); } static List keysList(Map map) { return cloneListSynchronizingOn(keys(map), map); } static List keysList(MultiSet ms) { return ms == null ? null : keysList(ms.map); } static Throwable unwrapTrivialExceptionWraps(Throwable e) { if (e == null) return e; while (e.getClass() == RuntimeException.class && e.getCause() != null && eq(e.getMessage(), str(e.getCause()))) e = e.getCause(); return e; } static Map newWeakMap() { return newWeakHashMap(); } static WeakReference newWeakReference(A a) { return a == null ? null : new WeakReference(a); } static String mainClassNameForClassLoader(ClassLoader cl) { return or((String) callOpt(cl, "mainClassName"), "main"); } static boolean methodIsStatic(Method m) { return (m.getModifiers() & Modifier.STATIC) != 0; } static boolean argumentCompatibleWithType(Object arg, Class type) { return arg == null ? !type.isPrimitive() : isInstanceX(type, arg); } static void arraycopy(Object[] a, Object[] b) { if (a != null && b != null) arraycopy(a, 0, b, 0, Math.min(a.length, b.length)); } static void arraycopy(Object src, int srcPos, Object dest, int destPos, int n) { if (n != 0) System.arraycopy(src, srcPos, dest, destPos, n); } static A[] arrayOfType(Class type, int n) { return makeArray(type, n); } static A[] arrayOfType(int n, Class type) { return arrayOfType(type, n); } static int parseHexChar(char c) { if (c >= '0' && c <= '9') return charDiff(c, '0'); if (c >= 'a' && c <= 'f') return charDiff(c, 'a') + 10; if (c >= 'A' && c <= 'F') return charDiff(c, 'A') + 10; return -1; } static int getIndentOfLine(String s) { int i = 0, n = l(s); while (i < n && s.charAt(i) == ' ') ++i; return i; } static boolean regionMatchesIC(String a, int offsetA, String b, int offsetB, int len) { return a != null && a.regionMatches(true, offsetA, b, offsetB, len); } static Set syncIdentityHashSet() { return (Set) synchronizedSet(identityHashSet()); } static Map syncHashMap() { return synchroHashMap(); } static Map singular_specials = litmap("children", "child", "images", "image", "chess", "chess"); static Set singular_specials2 = litciset("time", "machine", "line", "rule"); static String singular(String s) { if (s == null) return null; { String __1 = singular_specials.get(s); if (!empty(__1)) return __1; } // try answer hippoSingulars().get(lower(s)); if (singular_specials2.contains(dropSuffix("s", afterLastSpace(s)))) return dropSuffix("s", s); if (s.endsWith("ness")) return s; if (s.endsWith("ges")) return dropSuffix("s", s); if (endsWith(s, "bases")) return dropLast(s); s = dropSuffix("es", s); s = dropSuffix("s", s); return s; } static List getPlural_specials = ll("sheep", "fish"); static String getPlural(String s) { if (containsIgnoreCase(getPlural_specials, s)) return s; if (ewic(s, "y")) return dropSuffixIgnoreCase("y", s) + "ies"; if (ewicOneOf(s, "ss", "ch")) return s + "es"; if (ewic(s, "s")) return s; return s + "s"; } // This is a bit rough... finds static and non-static methods. static Method findMethodNamed(Object obj, String method) { if (obj == null) return null; if (obj instanceof Class) return findMethodNamed((Class) obj, method); return findMethodNamed(obj.getClass(), method); } static Method findMethodNamed(Class c, String method) { while (c != null) { for (Method m : c.getDeclaredMethods()) if (m.getName().equals(method)) { makeAccessible(m); return m; } c = c.getSuperclass(); } return null; } static void upgradeJavaXAndRestart() { run("#1001639"); restart(); sleep(); } static String imageServerLink(String md5OrID) { if (possibleMD5(md5OrID)) return "https://botcompany.de/images/md5/" + md5OrID; return imageServerLink(parseSnippetID(md5OrID)); } static String imageServerLink(long id) { return "https://botcompany.de/images/" + id; } static String fromUtf8(byte[] bytes) { try { return bytes == null ? null : new String(bytes, utf8charset()); } catch (Exception __e) { throw rethrow(__e); } } // can be set to work on different base dir static File javaxCodeDir_dir; static File javaxCodeDir() { return javaxCodeDir_dir != null ? javaxCodeDir_dir : new File(userHome(), "JavaX-Code"); } static File javaxCodeDir(String sub) { return newFile(javaxCodeDir(), sub); } static ReentrantLock fairLock() { return new ReentrantLock(true); } static String strOr(Object o, String ifNull) { return o == null ? ifNull : str(o); } static void lockOrFail(Lock lock, long timeout) { try { ping(); if (!lock.tryLock(timeout, TimeUnit.MILLISECONDS)) { String s = "Couldn't acquire lock after " + timeout + " ms."; if (lock instanceof ReentrantLock) { ReentrantLock l = (ReentrantLock) lock; s += " Hold count: " + l.getHoldCount() + ", owner: " + call(l, "getOwner"); } throw fail(s); } ping(); } catch (Exception __e) { throw rethrow(__e); } } static String getSnippetTitle(String id) { if (id == null) return null; if (!isSnippetID(id)) return "?"; IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.getSnippetTitle(id); return getSnippetTitle_noResourceLoader(id); } static String getSnippetTitle_noResourceLoader(String id) { try { if (isLocalSnippetID(id)) return localSnippetTitle(id); long parsedID = parseSnippetID(id); String url; if (isImageServerSnippet(parsedID)) url = imageServerURL() + "title/" + parsedID + muricaCredentialsQuery(); else if (isGeneralFileServerSnippet(parsedID)) url = "http://butter.botcompany.de:8080/files/name/" + parsedID; else url = tb_mainServer() + "/tb-int/getfield.php?id=" + parsedID + "&field=title" + standardCredentials_noCookies(); String title = trim(loadPageSilently(url)); if (title != null) try { saveTextFileIfChanged(snippetTitle_cacheFile(id), title); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } return or(title, "?"); } catch (Exception __e) { throw rethrow(__e); } } static String getSnippetTitle(long id) { return getSnippetTitle(fsI(id)); } static boolean isNormalQuoted(String s) { int l = l(s); if (!(l >= 2 && s.charAt(0) == '"' && lastChar(s) == '"')) return false; int j = 1; while (j < l) if (s.charAt(j) == '"') return j == l - 1; else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; return false; } static boolean isMultilineQuoted(String s) { if (!startsWith(s, "[")) return false; int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; return i < s.length() && s.charAt(i) == '['; } static String getCanonicalPath(File f) { try { return f == null ? null : f.getCanonicalPath(); } catch (Exception __e) { throw rethrow(__e); } } static String getCanonicalPath(String path) { return getCanonicalPath(newFile(path)); } static AutoCloseable tempCleaningUp() { return tempSetTL(ping_isCleanUpThread, true); } static void closeAllWriters(Collection l) { for (Writer w : unnull(l)) { try { w.close(); } catch (Throwable __e) { _handleException(__e); } } } static TimeZone localTimeZone() { return getTimeZone(standardTimeZone()); // TimeZone.getDefault()? } static JTextField setTextAndSelectAll(final JTextField tf, final String text) { if (tf != null) { swing(new Runnable() { public void run() { try { tf.setText(text); tf.selectAll(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "tf.setText(text);\r\n tf.selectAll();"; } }); } return tf; } static boolean eqic(String a, String b) { if ((a == null) != (b == null)) return false; if (a == null) return true; return a.equalsIgnoreCase(b); } static boolean eqic(char a, char b) { if (a == b) return true; char u1 = Character.toUpperCase(a); char u2 = Character.toUpperCase(b); if (u1 == u2) return true; return Character.toLowerCase(u1) == Character.toLowerCase(u2); } static boolean matchStart(String pat, String s) { return matchStart(pat, s, null); } // matches are as you expect, plus an extra item for the rest string static boolean matchStart(String pat, String s, Matches matches) { if (s == null) return false; return matchStart(pat, parse3_cachedInput(s), matches); } static boolean matchStart(String pat, List toks, Matches matches) { if (toks == null) return false; List tokpat = parse3_cachedPattern(pat); if (toks.size() < tokpat.size()) return false; String[] m = match2(tokpat, toks.subList(0, tokpat.size())); // print(structure(tokpat) + " on " + structure(toks) + " => " + structure(m)); if (m == null) return false; if (matches != null) { matches.m = new String[m.length + 1]; arraycopy(m, matches.m); // for Matches.rest() matches.m[m.length] = joinSubList(toks, tokpat.size(), toks.size()); } return true; } static String sendToLocalBotOpt(String bot, String text, Object... args) { if (bot == null) return null; text = format(text, args); DialogIO channel = findBot(bot); try { if (channel == null) { print(quote(bot) + " not found, skipping send: " + quote(text)); return null; } try { channel.readLine(); print(shorten(bot + "> " + text, 200)); channel.sendLine(text); String s = channel.readLine(); print(shorten(bot + "< " + s, 200)); return s; } catch (Throwable e) { e.printStackTrace(); return null; } } finally { _close(channel); } } static String fsI_flex(String s) { return startsWithDigit(s) ? "#" + s : s; } static boolean exposeMethods2_debug = false; static String exposeMethods2(Object receiver, String s, List methodNames) { return exposeMethods2(receiver, s, methodNames, null); } static String exposeMethods2(Object receiver, String s, List methodNames, Lock lock) { Matches m = new Matches(); if (exposeMethods2_debug) print("Received: " + s); if (match("call *", s, m)) { List l; if (isIdentifier(m.unq(0))) l = ll(m.unq(0)); else // we used to have safeUnstructure here l = (List) unstructure(m.unq(0)); String method = getString(l, 0); if (!contains(methodNames, method)) throw fail("Method not allowed: " + method); if (lock != null) lock.lock(); try { if (exposeMethods2_debug) print("Calling: " + method); Object o = call(receiver, method, asObjectArray(subList(l, 1))); if (exposeMethods2_debug) print("Got: " + getClassName(o)); return ok2(structure(o)); } finally { if (lock != null) lock.unlock(); } } if (match("list methods", s)) return ok2(structure(methodNames)); return null; } static int makeBot(String greeting) { return makeAndroid3(greeting).port; } static Android3 makeBot(Android3 a) { makeAndroid3(a); return a; } static Android3 makeBot(String greeting, Object responder) { Android3 a = new Android3(greeting); a.responder = makeResponder(responder); makeBot(a); return a; } static Android3 makeBot() { return makeAndroid3(defaultBotName()); } static List listFilesOnly(String dir) { return listFilesOnly(new File(dir)); } static List listFilesOnly(File... dirs) { return concatMap(rcurry("listFilesWithSuffix", ""), dirs); } static Comparator mapComparator(final Map map) { return new Comparator() { public int compare(A a, A b) { return cmp(map.get(a), map.get(b)); } }; } static String quoteUnlessIdentifierOrInteger(String s) { return quoteIfNotIdentifierOrInteger(s); } static A println(A a) { return print(a); } static String imageServerURL() { return or2(trim(loadTextFile(javaxDataDir("image-server-url.txt"))), "http://botcompany.de/images/raw/"); } static volatile boolean muricaPassword_pretendNotAuthed = false; static String muricaPassword() { if (muricaPassword_pretendNotAuthed) return null; return trim(loadTextFile(muricaPasswordFile())); } static String fileServerURL() { return "https://botcompany.de/files"; } public static File mkdirsFor(File file) { return mkdirsForFile(file); } static void copyStreamWithPrints(InputStream in, OutputStream out, String pat) { try { byte[] buf = new byte[65536]; int total = 0; while (true) { int n = in.read(buf); if (n <= 0) return; out.write(buf, 0, n); if ((total + n) / 100000 > total / 100000) print(pat.replace("{*}", str(roundDownTo(100000, total)))); total += n; } } catch (Exception __e) { throw rethrow(__e); } } static File renameFile_assertTrue(File a, File b) { try { // no rename necessary if (a.equals(b)) return b; if (!a.exists()) throw fail("Source file not found: " + f2s(a)); if (b.exists()) throw fail("Target file exists: " + f2s(b)); mkdirsForFile(b); if (!a.renameTo(b)) throw fail("Can't rename " + f2s(a) + " to " + f2s(b)); return b; } catch (Exception __e) { throw rethrow(__e); } } static boolean isSubstanceLAF() { return substanceLookAndFeelEnabled(); } // menuMaker = voidfunc(JPopupMenu) // return true if menu could be added static boolean titlePopupMenu(final Component c, final Object menuMaker) { JComponent titleBar = getTitlePaneComponent(getPossiblyInternalFrame(c)); if (titleBar == null) { print("Can't add title right click!"); return false; } else { componentPopupMenu(titleBar, menuMaker); return true; } } static void toggleAlwaysOnTop(JFrame frame) { frame.setAlwaysOnTop(!frame.isAlwaysOnTop()); } static A oneOf(List l) { return empty(l) ? null : l.get(new Random().nextInt(l.size())); } static char oneOf(String s) { return empty(s) ? '?' : s.charAt(random(l(s))); } static String oneOf(String... l) { return oneOf(asList(l)); } static A collectionGet(Collection c, int idx) { if (c == null || idx < 0 || idx >= l(c)) return null; if (c instanceof List) return listGet((List) c, idx); Iterator it = c.iterator(); for (int i = 0; i < idx; i++) if (it.hasNext()) it.next(); else return null; return it.hasNext() ? it.next() : null; } static Throwable getException(Runnable r) { try { callF(r); return null; } catch (Throwable e) { return e; } } static Method findMethod_cached(Object o, String method, Object... args) { try { if (o == null) return null; if (o instanceof Class) { _MethodCache cache = callOpt_getCache(((Class) o)); List methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (isStaticMethod(m) && findMethod_checkArgs(m, args, false)) return m; return null; } else { _MethodCache cache = callOpt_getCache(o.getClass()); List methods = cache.cache.get(method); if (methods != null) for (Method m : methods) if (findMethod_checkArgs(m, args, false)) return m; return null; } } catch (Exception __e) { throw rethrow(__e); } } static List dropFirstThreeAndLastThree(List l) { return dropFirstAndLast(3, l); } // TODO: extended multi-line strings static int javaTok_n, javaTok_elements; static boolean javaTok_opt = false; static List javaTok(String s) { ++javaTok_n; ArrayList tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !regionMatches(s, j, "*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(javaTok_substringN(s, i, j)); i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); // scan for non-whitespace // Special JavaX syntax: 'identifier if (c == '\'' && Character.isJavaIdentifierStart(d) && i + 2 < l && "'\\".indexOf(s.charAt(i + 2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { int c2 = s.charAt(j); if (c2 == opener || c2 == '\n' && opener == '\'') { // allow multi-line strings, but not for ' ++j; break; } else if (c2 == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) // for stuff like "don't" do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || s.charAt(j) == '\'')); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); // Long constants like 1L if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j < l && !regionMatches(s, j, "]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !regionMatches(s, j, "]=]")); j = Math.min(j + 3, l); } else ++j; tok.add(javaTok_substringC(s, i, j)); i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static List javaTok(List tok) { return javaTokWithExisting(join(tok), tok); } static List tok_combineCurlyBrackets_keep(List tok) { List l = new ArrayList(); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && eq(t, "{")) { int j = findEndOfCurlyBracketPart(tok, i); l.add(joinSubList(tok, i, j)); i = j - 1; } else l.add(t); } return l; } static boolean startsWithAndEndsWith(String s, String prefix, String suffix) { return startsWith(s, prefix) && endsWith(s, suffix); } static ThreadLocal componentPopupMenu_mouseEvent; static void componentPopupMenu_init() { { swing(new Runnable() { public void run() { try { if (componentPopupMenu_mouseEvent == null) componentPopupMenu_mouseEvent = (ThreadLocal) vm_generalMap_get("mouseEvent"); if (componentPopupMenu_mouseEvent == null) vm_generalMap_put("componentPopupMenu_mouseEvent", componentPopupMenu_mouseEvent = new ThreadLocal()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "if (componentPopupMenu_mouseEvent == null)\r\n componentPopupMenu_mouseEve..."; } }); } } // menuMaker = voidfunc(JPopupMenu) static void componentPopupMenu(final JComponent component, final Object menuMaker) { if (component == null || menuMaker == null) return; { swing(new Runnable() { public void run() { try { Object adapter = componentPopupMenu_initForComponent(component); ((List) _get(adapter, "maker")).add(menuMaker); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "Object adapter = componentPopupMenu_initForComponent(component);\r\n ((List)..."; } }); } } static Object componentPopupMenu_initForComponent(final JComponent component) { return component == null ? null : swing(new F0() { public Object get() { try { componentPopupMenu_init(); Object adapter = findComponentPopupMenuListener_gen(component); if (adapter == null) { componentPopupMenu_Adapter a = new componentPopupMenu_Adapter(); component.addMouseListener(a); adapter = a; } return adapter; } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "componentPopupMenu_init();\r\n O adapter = findComponentPopupMenuListener_ge..."; } }); } static class componentPopupMenu_Adapter extends MouseAdapter { List maker = new ArrayList(); boolean internalFrameLeftButtonMagic = false; Point pressedAt; public void mousePressed(MouseEvent e) { displayMenu(e); pressedAt = internalFrameLeftButtonMagic && e.getClickCount() == 1 && internalFrameActive(e.getComponent()) ? e.getLocationOnScreen() : null; } public void mouseReleased(MouseEvent e) { // TODO: show a little less often on left mouse click if (internalFrameLeftButtonMagic && eq(pressedAt, e.getLocationOnScreen())) displayMenu2(e); else displayMenu(e); } void displayMenu(MouseEvent e) { if (e.getSource() instanceof JInternalFrame) return; if (e.isPopupTrigger()) displayMenu2(e); } void displayMenu2(MouseEvent e) { JPopupMenu menu = new JPopupMenu(); int emptyCount = menu.getComponentCount(); AutoCloseable __1 = tempSetTL(componentPopupMenu_mouseEvent, e); try { for (Object menuMaker : maker) pcallF(menuMaker, menu); vmBus_send("showingPopupMenu", e.getComponent(), menu); // show menu if any items in it if (menu.getComponentCount() != emptyCount) menu.show(e.getComponent(), e.getX(), e.getY()); } finally { _close(__1); } } } static Object fieldGet(Field f, Object o) { try { return f == null ? null : f.get(o); } catch (Exception __e) { throw rethrow(__e); } } // Actual signature is longer, but we're lazy static byte[] isGIF_magic = bytesFromHex("47494638"); static boolean isGIF(byte[] data) { return byteArrayStartsWith(data, isGIF_magic); } static boolean isGIF(File f) { return isGIF(loadBeginningOfBinaryFile(f, l(isGIF_magic))); } static void setVar(IVar v, A value) { if (v != null) v.set(value); } static A assertEquals(Object x, A y) { return assertEquals(null, x, y); } static A assertEquals(String msg, Object x, A y) { if (assertVerbose()) return assertEqualsVerbose(msg, x, y); if (!(x == null ? y == null : x.equals(y))) throw fail((msg != null ? msg + ": " : "") + y + " != " + x); return y; } static List javaTokC(String s) { if (s == null) return null; int l = s.length(); ArrayList tok = new ArrayList(); int i = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { // end at \n to not propagate unclosed string literal errors ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) // for stuff like "don't" do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); // Long constants like 1L if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else ++j; tok.add(javaTok_substringC(s, i, j)); i = j; } return tok; } static A popLast(List l) { return liftLast(l); } static List popLast(int n, List l) { return liftLast(n, l); } static String actualMCDollar() { return actualMC().getName() + "$"; } static void quoteToPrintWriter(String s, PrintWriter out) { if (s == null) { out.print("null"); return; } out.print('"'); int l = s.length(); for (int i = 0; i < l; i++) { char c = s.charAt(i); if (c == '\\' || c == '"') { out.print('\\'); out.print(c); } else if (c == '\r') out.print("\\r"); else if (c == '\n') out.print("\\n"); else if (c == '\0') out.print("\\0"); else out.print(c); } out.print('"'); } static String quoteCharacter(char c) { if (c == '\'') return "'\\''"; if (c == '\\') return "'\\\\'"; if (c == '\r') return "'\\r'"; if (c == '\n') return "'\\n'"; if (c == '\t') return "'\\t'"; return "'" + c + "'"; } static boolean isCISet_gen(Iterable l) { return l instanceof TreeSet && className(((TreeSet) l).comparator()).contains("CIComp"); } static boolean isJavaXClassName(String s) { return startsWithOneOf(s, "main$", "loadableUtils."); } static List unwrapSynchronizedList(List l) { if (l instanceof SynchronizedList) return ((SynchronizedList) l).list; if (eqOneOf(className(l), "java.util.Collections$SynchronizedList", "java.util.Collections$SynchronizedRandomAccessList")) return (List) get_raw(l, "list"); return l; } static boolean isCIMap_gen(Map map) { return map instanceof TreeMap && className(((TreeMap) map).comparator()).contains("CIComp"); } static Map unwrapSynchronizedMap(Map map) { if (eqOneOf(className(map), "java.util.Collections$SynchronizedMap", "java.util.Collections$SynchronizedSortedMap", "java.util.Collections$SynchronizedNavigableMap")) return (Map) get_raw(map, "m"); return map; } static String boolArrayToHex(boolean[] a) { return bytesToHex(boolArrayToBytes(a)); } static Pair arrayTypeAndDimensions(Object o) { return arrayTypeAndDimensions(_getClass(o)); } static Pair arrayTypeAndDimensions(Class c) { if (c == null || !c.isArray()) return null; Class elem = c.getComponentType(); if (elem.isArray()) return mapPairB(arrayTypeAndDimensions(elem), dim -> dim + 1); return pair(elem, 1); } static Iterator emptyIterator() { return Collections.emptyIterator(); } static String shortDynamicClassName(Object o) { if (o instanceof DynamicObject && ((DynamicObject) o).className != null) return ((DynamicObject) o).className; return shortClassName(o); } static int stdcompare(Number a, Number b) { return cmp(a, b); } static int stdcompare(String a, String b) { return cmp(a, b); } static int stdcompare(long a, long b) { return a < b ? -1 : a > b ? 1 : 0; } static int stdcompare(Object a, Object b) { return cmp(a, b); } static Map getDeclaredFields_cache = newDangerousWeakHashMap(); static Field[] getDeclaredFields_cached(Class c) { Field[] fields; synchronized (getDeclaredFields_cache) { fields = getDeclaredFields_cache.get(c); if (fields == null) { getDeclaredFields_cache.put(c, fields = c.getDeclaredFields()); for (Field f : fields) makeAccessible(f); } } return fields; } static boolean startsWithDigit(String s) { return nempty(s) && isDigit(s.charAt(0)); } static Map putAll(Map a, Map b) { if (a != null && b != null) a.putAll(b); return a; } static Map putAll(Map a, Object... b) { if (a != null) litmap_impl(a, b); return a; } static int countDots(String s) { int n = l(s), count = 0; for (int i = 0; i < n; i++) if (s.charAt(i) == '.') ++count; return count; } static int indexOfIgnoreCase_manual(String a, String b) { return indexOfIgnoreCase_manual(a, b, 0); } static int indexOfIgnoreCase_manual(String a, String b, int i) { int la = strL(a), lb = strL(b); if (la < lb) return -1; int n = la - lb; loop: for (; i <= n; i++) { for (int j = 0; j < lb; j++) { char c1 = a.charAt(i + j), c2 = b.charAt(j); if (!eqic(c1, c2)) continue loop; } return i; } return -1; } static Producer javaTokC_noMLS_iterator(final String s) { return javaTokC_noMLS_iterator(s, 0); } static Producer javaTokC_noMLS_iterator(final String s, final int startIndex) { return new Producer() { final int l = s.length(); int i = startIndex; public String next() { if (i >= l) return null; int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } i = j; if (i >= l) return null; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener || s.charAt(j) == '\n') { // end at \n to not propagate unclosed string literal errors ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); // Long constants like 1L if (j < l && s.charAt(j) == 'L') ++j; } else ++j; String t = quickSubstring(s, i, j); i = j; return t; } }; } static Producer javaTokC_noMLS_onReader(final BufferedReader r) { final class X implements Producer { // stores from "i" StringBuilder buf = new StringBuilder(); // just not '\0' char c, d, e = 'x'; X() { // fill c, d and e nc(); nc(); nc(); } // get next character(s) into c, d and e void nc() { try { c = d; d = e; if (e == '\0') return; int i = r.read(); e = i < 0 ? '\0' : // shouldn't happen anymore i == '\0' ? // shouldn't happen anymore '_' : (char) i; } catch (Exception __e) { throw rethrow(__e); } } void ncSave() { if (c != '\0') { buf.append(c); nc(); } } public String next() { // scan for whitespace while (c != '\0') { if (c == ' ' || c == '\t' || c == '\r' || c == '\n') nc(); else if (c == '/' && d == '*') { do nc(); while (c != '\0' && !(c == '*' && d == '/')); nc(); nc(); } else if (c == '/' && d == '/') { do nc(); while (c != '\0' && "\r\n".indexOf(c) < 0); } else break; } if (c == '\0') return null; // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ncSave(); while (c != '\0') { if (c == opener || c == '\n') { // end at \n to not propagate unclosed string literal errors ncSave(); break; } else if (c == '\\') { ncSave(); ncSave(); } else ncSave(); } } else if (Character.isJavaIdentifierStart(c)) // for stuff like "don't" do ncSave(); while (Character.isJavaIdentifierPart(c) || c == '\''); else if (Character.isDigit(c)) { do ncSave(); while (Character.isDigit(c)); // Long constants like 1L if (c == 'L') ncSave(); } else ncSave(); String t = buf.toString(); buf.setLength(0); return t; } } return new X(); } static HashMap findClass_fullName_cache = new HashMap(); // returns null on not found // this is the simple version that is not case-tolerant static Class findClass_fullName(String name) { synchronized (findClass_fullName_cache) { if (findClass_fullName_cache.containsKey(name)) return findClass_fullName_cache.get(name); Class c; try { c = Class.forName(name); } catch (ClassNotFoundException e) { c = null; } findClass_fullName_cache.put(name, c); return c; } } static String unquoteUsingCharArray(String s, char[] buf) { if (s == null) return null; if (startsWith(s, '[')) { int i = 1; while (i < s.length() && s.charAt(i) == '=') ++i; if (i < s.length() && s.charAt(i) == '[') { String m = s.substring(1, i); if (s.endsWith("]" + m + "]")) return s.substring(i + 1, s.length() - i - 1); } } if (s.length() > 1) { char c = s.charAt(0); if (c == '\"' || c == '\'') { int l = endsWith(s, c) ? s.length() - 1 : s.length(); // fallback if (l > buf.length) return unquote(s); int n = 0; for (int i = 1; i < l; i++) { char ch = s.charAt(i); if (ch == '\\') { char nextChar = (i == l - 1) ? '\\' : s.charAt(i + 1); // Octal escape? if (nextChar >= '0' && nextChar <= '7') { String code = "" + nextChar; i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; if ((i < l - 1) && s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '7') { code += s.charAt(i + 1); i++; } } buf[n++] = (char) Integer.parseInt(code, 8); continue; } switch(nextChar) { case '\"': ch = '\"'; break; case '\\': ch = '\\'; break; case 'b': ch = '\b'; break; case 'f': ch = '\f'; break; case 'n': ch = '\n'; break; case 'r': ch = '\r'; break; case 't': ch = '\t'; break; case '\'': ch = '\''; break; // Hex Unicode: u???? case 'u': if (i >= l - 5) { ch = 'u'; break; } int code = Integer.parseInt("" + s.charAt(i + 2) + s.charAt(i + 3) + s.charAt(i + 4) + s.charAt(i + 5), 16); char[] x = Character.toChars(code); int lx = x.length; for (int j = 0; j < lx; j++) buf[n++] = x[j]; i += 5; continue; default: // added by Stefan ch = nextChar; } i++; } buf[n++] = ch; } return new String(buf, 0, n); } } // not quoted - return original return s; } static boolean structure_isMarker(String s, int i, int j) { if (i >= j) return false; if (s.charAt(i) != 'm') return false; ++i; while (i < j) { char c = s.charAt(i); if (c < '0' || c > '9') return false; ++i; } return true; } static String internIfLongerThan(String s, int l) { return s == null ? null : l(s) >= l ? intern(s) : s; } static char unquoteCharacter(String s) { assertTrue(s.startsWith("'") && s.length() > 1); return unquote("\"" + s.substring(1, s.endsWith("'") ? s.length() - 1 : s.length()) + "\"").charAt(0); } static BigInteger parseBigInt(String s) { return new BigInteger(s); } static float parseFloat(String s) { return Float.parseFloat(s); } static boolean isLongConstant(String s) { if (!s.endsWith("L")) return false; s = s.substring(0, l(s) - 1); return isInteger(s); } static TreeMap ciMap() { return caseInsensitiveMap(); } static List parseList(String s) { return (List) safeUnstructure(s); } static List synchroLinkedList() { return Collections.synchronizedList(new LinkedList()); } static NavigableMap synchroNavigableMap(NavigableMap map) { return (NavigableMap) call(Collections.class, "synchronizedNavigableMap", map); } static SortedMap synchroSortedMap(SortedMap map) { return new SynchronizedSortedMap(map); } static boolean[] boolArrayFromBytes(byte[] a, int n) { boolean[] b = new boolean[n]; int m = min(n, l(a) * 8); for (int i = 0; i < m; i++) b[i] = (a[i / 8] & 1 << (i & 7)) != 0; return b; } static Constructor nuStubInnerObject_findConstructor(Class c) { return nuStubInnerObject_findConstructor(c, null); } static Constructor nuStubInnerObject_findConstructor(Class c, Object classFinder) { try { Class outerType = getOuterClass(c, classFinder); Constructor m = c.getDeclaredConstructor(outerType); makeAccessible(m); return m; } catch (Exception __e) { throw rethrow(__e); } } static Map nuEmptyObject_cache = newDangerousWeakHashMap(); static A nuEmptyObject(Class c) { try { Constructor ctr; synchronized (nuEmptyObject_cache) { ctr = nuEmptyObject_cache.get(c); if (ctr == null) { nuEmptyObject_cache.put(c, ctr = nuEmptyObject_findConstructor(c)); makeAccessible(ctr); } } try { return (A) ctr.newInstance(); } catch (InstantiationException e) { if (empty(e.getMessage())) if ((c.getModifiers() & Modifier.ABSTRACT) != 0) throw fail("Can't instantiate abstract class " + className(c), e); else throw fail("Can't instantiate " + className(c), e); else throw rethrow(e); } } catch (Exception __e) { throw rethrow(__e); } } static Constructor nuEmptyObject_findConstructor(Class c) { for (Constructor m : c.getDeclaredConstructors()) if (m.getParameterTypes().length == 0) return m; throw fail("No default constructor declared in " + c.getName()); } static void setOptAllDyn_pcall(DynamicObject o, Map fields) { if (fields == null || o == null) return; HashMap fieldMap = instanceFieldsMap(o); for (Map.Entry e : fields.entrySet()) { try { String field = e.getKey(); Object val = e.getValue(); Field f = fieldMap.get(field); if (f != null) smartSet(f, o, val); else { dynamicObject_setRawFieldValue(o, intern(field), val); } } catch (Throwable __e) { _handleException(__e); } } } static void setOptAll_pcall(Object o, Map fields) { if (fields == null) return; for (String field : keys(fields)) try { setOpt(o, field, fields.get(field)); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } static void setOptAll_pcall(Object o, Object... values) { // values = expandParams(c.getClass(), values); warnIfOddCount(values); for (int i = 0; i + 1 < l(values); i += 2) { String field = (String) values[i]; Object value = values[i + 1]; try { setOpt(o, field, value); } catch (Throwable __e) { print(exceptionToStringShort(__e)); } } } static void fixOuterRefs(Object o) { try { if (o == null) return; Field[] l = thisDollarOneFields(o.getClass()); if (l.length <= 1) return; Object father = null; for (Field f : l) { father = f.get(o); if (father != null) break; } if (father == null) return; for (Field f : l) f.set(o, father); } catch (Exception __e) { throw rethrow(__e); } } static void pcallOpt_noArgs(Object o, String method) { try { callOpt_noArgs(o, method); } catch (Throwable __e) { _handleException(__e); } } static RuntimeException todo() { throw new RuntimeException("TODO"); } static RuntimeException todo(Object msg) { throw new RuntimeException("TODO: " + msg); } static Object newMultiDimensionalOuterArray(Class elementType, int dimensions, int length) { int[] dims = new int[dimensions]; dims[0] = length; return Array.newInstance(elementType, dims); } static int[] toIntArray(Collection l) { int[] a = new int[l(l)]; int i = 0; if (a.length != 0) for (int x : l) a[i++] = x; return a; } static double[] toDoubleArray(Collection l) { double[] a = new double[l(l)]; int i = 0; if (a.length != 0) for (double x : l) a[i++] = x; return a; } static TreeSet ciSet() { return caseInsensitiveSet(); } static boolean jmatch(String pat, String s) { return jmatch(pat, s, null); } static boolean jmatch(String pat, String s, Matches matches) { if (s == null) return false; return jmatch(pat, javaTok(s), matches); } static boolean jmatch(String pat, List toks) { return jmatch(pat, toks, null); } static boolean jmatch(String pat, List toks, Matches matches) { List tokpat = javaTok(pat); String[] m = match2(tokpat, toks); // print(structure(tokpat) + " on " + structure(toks) + " => " + structure(m)); if (m == null) return false; else { if (matches != null) matches.m = m; return true; } } static ThreadLocal dynamicObjectIsLoading_threadLocal() { return DynamicObject_loading; } static Map newFindBot2_cache = synchroHashMap(); static boolean newFindBot2_verbose = false; static DialogIO newFindBot2(String name) { Integer port = newFindBot2_cache.get(name); if (port != null) { if (newFindBot2_verbose) print("newFindBot2: testing " + name + " => " + port); DialogIO io = talkTo(port); String q = format("has bot *", name); String s = io.ask(q); if (match("yes", s)) { io = talkToSubBot(name, io); // put some hello string in (yes, this should be improved.) call(io, "pushback", "?"); return io; } // bot not there anymore - remove cache entry newFindBot2_cache.remove(name); if (newFindBot2_verbose) print("newFindBot2: dropping " + name + " => " + port); } DialogIO io = findBot(name); if (io != null) { newFindBot2_cache.put(name, io.getPort()); if (newFindBot2_verbose) print("newFindBot2: remembering " + name + " => " + port); } return io; } static boolean isLoopbackIP(String ip) { return eq(ip, "127.0.0.1"); } static int myVMPort() { List records = (List) (get(getJavaX(), "record_list")); Object android = last(records); return or0((Integer) get(android, "port")); } static String thisVMGreeting() { List record_list = (List) (get(getJavaX(), "record_list")); // Should be of class Android3 Object android = first(record_list); return getString(android, "greeting"); } static String sendToThisVM_newThread(String s, Object... args) { final String _s = format(s, args); try { return (String) evalInNewThread(new F0() { public Object get() { try { return callStaticAnswerMethod(getJavaX(), _s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret callStaticAnswerMethod(getJavaX(), _s);"; } }); } catch (Throwable e) { e = getInnerException(e); printStackTrace(e); return str(e); } } static A popFirst(List l) { if (empty(l)) return null; A a = first(l); l.remove(0); return a; } static A popFirst(Collection l) { if (empty(l)) return null; A a = first(l); l.remove(a); return a; } static List popFirst(int n, List l) { List part = cloneSubList(l, 0, n); removeSubList(l, 0, n); return part; } static boolean fileExists(String path) { return path != null && new File(path).exists(); } static boolean fileExists(File f) { return f != null && f.exists(); } static String roundBracket(String s) { return "(" + s + ")"; } static String _computerID; static Lock computerID_lock = lock(); public static String computerID() { if (_computerID == null) { Lock __0 = computerID_lock; lock(__0); try { if (_computerID != null) return _computerID; File file = computerIDFile(); _computerID = loadTextFile(file.getPath()); if (_computerID == null) { // legacy load _computerID = loadTextFile(userDir(".tinybrain/computer-id")); if (_computerID == null) _computerID = makeRandomID(12, new SecureRandom()); saveTextFile(file, _computerID); } } finally { unlock(__0); } } return _computerID; } static String joinNempties(String sep, Object... strings) { return joinStrings(sep, strings); } static String joinNempties(String sep, Iterable strings) { return joinStrings(sep, strings); } static String stream2string(InputStream in) { return utf8streamToString(in); } static char lastChar(String s) { return empty(s) ? '\0' : s.charAt(l(s) - 1); } static Map syncMRUCache(int size) { return synchroMap(new MRUCache(size)); } static JTextArea jTextAreaWithUndo() { return jTextAreaWithUndo(""); } static JTextArea jTextAreaWithUndo(final String text) { return jenableUndoRedo(swingNu(JTextArea.class, text)); } static AutoCloseable tempActivity(Object r) { return null; } static boolean allPaused() { return ping_pauseAll; } static void cancelTimer(javax.swing.Timer timer) { if (timer != null) timer.stop(); } static void cancelTimer(java.util.Timer timer) { if (timer != null) timer.cancel(); } static void cancelTimer(Object o) { if (o instanceof java.util.Timer) cancelTimer((java.util.Timer) o); else if (o instanceof javax.swing.Timer) cancelTimer((javax.swing.Timer) o); else if (o instanceof AutoCloseable) { try { ((AutoCloseable) o).close(); } catch (Throwable __e) { _handleException(__e); } } } static void bindTimerToComponent(final Timer timer, JFrame f) { bindTimerToComponent(timer, f.getRootPane()); } static void bindTimerToComponent(final Timer timer, JComponent c) { if (c.isShowing()) timer.start(); c.addAncestorListener(new AncestorListener() { public void ancestorAdded(AncestorEvent event) { timer.start(); } public void ancestorRemoved(AncestorEvent event) { timer.stop(); } public void ancestorMoved(AncestorEvent event) { } }); } static Object[] mapToObjectArray(Map map) { List l = new ArrayList(); for (Object o : keys(map)) { l.add(o); l.add(map.get(o)); } return toObjectArray(l); } static Object[] mapToObjectArray(Object f, Collection l) { int n = l(l); Object[] array = new Object[n]; if (n != 0) { Iterator it = iterator(l); for (int i = 0; i < n; i++) array[i] = callF(f, it.next()); } return array; } static Object[] mapToObjectArray(Object f, Object[] l) { int n = l(l); Object[] array = new Object[n]; for (int i = 0; i < n; i++) array[i] = callF(f, l[i]); return array; } static Object[] mapToObjectArray(Collection l, IF1 f) { return mapToObjectArray(f, l); } static Object[] mapToObjectArray(A[] l, IF1 f) { return mapToObjectArray(f, l); } static Object[] mapToObjectArray(IF1 f, A[] l) { int n = l(l); Object[] array = new Object[n]; for (int i = 0; i < n; i++) array[i] = f.get(l[i]); return array; } // this should be on by default now I think, but it may break // legacy code... static ThreadLocal htmlencode_forParams_useV2 = new ThreadLocal(); static String htmlencode_forParams(String s) { if (s == null) return ""; if (isTrue(htmlencode_forParams_useV2.get())) return htmlencode_forParams_v2(s); StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>') { out.append("&#"); out.append((int) c); out.append(';'); } else out.append(c); } return out.toString(); } static char charAt(String s, int i) { return s != null && i >= 0 && i < s.length() ? s.charAt(i) : '\0'; } static boolean isLetter(char c) { return Character.isLetter(c); } static List codeTokens(List tok) { return codeTokensOnly(tok); } static List tok_joinMinusIdentifiers(List tok) { for (int i = 1; i + 4 < l(tok); i += 2) if (isMinusIdentifier(get(tok, i)) && eq(get(tok, i + 2), "-") && isIdentifier(get(tok, i + 4))) { replaceSublist(tok, i, i + 5, ll(join(subList(tok, i, i + 5)))); i -= 2; } return tok; } static List htmlFineTok(String s) { List tok = new ArrayList(); int l = s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else break; } tok.add(quickSubstring(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener) /*|| s.charAt(j) == '\n'*/ { // allow multi-line strings ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) // for stuff like "don't" do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); // Long constants like 1L if (j < l && s.charAt(j) == 'L') ++j; } else ++j; tok.add(quickSubstring(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static A printStruct(String prefix, A a) { printStructure(prefix, a); return a; } static A printStruct(A a) { printStructure(a); return a; } static boolean isMinusIdentifier(String s) { if (empty(s)) return false; if (!Character.isJavaIdentifierStart(s.charAt(0)) && !s.startsWith("-")) return false; for (int i = 1; i < s.length(); i++) if (!Character.isJavaIdentifierPart(s.charAt(i)) && s.charAt(i) != '-') return false; return true; } static String htmlunquote(String s) { if (s.startsWith("'") && s.endsWith("'") && s.length() >= 2 || s.startsWith("\"") && s.endsWith("\"") && s.length() >= 2) s = s.substring(1, s.length() - 1); return htmldecode(s); } static A[] arrayOfSameType(A[] a, int n) { return newObjectArrayOfSameType(a, n); } static Comparator caseInsensitiveComparator() { return betterCIComparator(); } // f : Matcher -> S static String regexReplace(String s, String pat, Object f) { Matcher m = Pattern.compile(pat).matcher(s); return regexReplace(m, f); } static String regexReplace(String s, String pat, String replacement) { return regexpReplace_direct(s, pat, replacement); } static String regexReplace(Matcher m, Object f) { StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, m.quoteReplacement(str(callF(f, m)))); m.appendTail(buf); return str(buf); } static String regexReplace(String s, String pat, IF1 f) { return regexReplace(s, pat, (Object) f); } static Matcher regexpMatcherIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static String regexpReplaceIC_direct(String s, String pat, String replacement) { Matcher m = regexpIC(pat, s); StringBuffer buf = new StringBuffer(); while (m.find()) m.appendReplacement(buf, replacement); m.appendTail(buf); return str(buf); } static File standardLogFile() { return getProgramFile("log"); } static void logQuoted(String logFile, String line) { logQuoted(getProgramFile(logFile), line); } static void logQuoted(File logFile, String line) { appendToFile(logFile, quote(line) + "\n"); } static A heldInstance(Class c) { List l = holdInstance_l.get(); for (int i = l(l) - 1; i >= 0; i--) { Object o = l.get(i); if (isInstanceOf(o, c)) return (A) o; } throw fail("No instance of " + className(c) + " held"); } static List vmBus_queryAll(String msg, Object... args) { Object arg = vmBus_wrapArgs(args); List out = new ArrayList(); for (Object o : unnull(vm_busListeners_live())) addIfNotNull(out, pcallF(o, msg, arg)); for (Object o : unnull(vm_busListenersByMessage_live().get(msg))) addIfNotNull(out, pcallF(o, msg, arg)); return out; } static File dirOfFile(File f) { return f == null ? null : f.getParentFile(); } static void multiMapPut(Map> map, A a, B b) { List l = map.get(a); if (l == null) map.put(a, l = new ArrayList()); l.add(b); } static Object defaultDefaultClassFinder() { return new F1() { public Class get(String name) { Class c = get2(name); return c; } Class get2(String name) { // special invocation to find main class irrelevant of name if (eq(name, "
")) return mc(); { Class c = findClass_fullName(name); if (c != null) return c; } if (startsWithAny(name, "loadableUtils.utils$", "main$", mcDollar())) for (String pkg : ll("loadableUtils.utils$", mcDollar())) { String newName = pkg + afterDollar(name); { Class c = findClass_fullName(newName); if (c != null) return c; } } return null; } }; } static List listFilesWithSuffix(File dir, String suffix) { List l = new ArrayList(); for (File f : listFiles(dir)) if (!f.isDirectory() && (empty(suffix) || endsWithIgnoreCase(f.getName(), suffix))) l.add(f); return l; } static void nohupJavax(final String javaxargs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs);"; } }); } } static void nohupJavax(final String javaxargs, final String vmArgs) { { startThread(new Runnable() { public void run() { try { call(hotwireOnce("#1008562"), "nohupJavax", javaxargs, vmArgs); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "call(hotwireOnce(\"#1008562\"), \"nohupJavax\", javaxargs, vmArgs);"; } }); } } static ArrayList cloneListSynchronizingOn(Collection l, Object mutex) { if (l == null) return new ArrayList(); synchronized (mutex) { return new ArrayList(l); } } static A[] makeArray(Class type, int n) { return (A[]) Array.newInstance(type, n); } static int charDiff(char a, char b) { return (int) a - (int) b; } static int charDiff(String a, char b) { return charDiff(stringToChar(a), b); } static Set synchronizedSet() { return synchroHashSet(); } static Set synchronizedSet(Set set) { return Collections.synchronizedSet(set); } static Set identityHashSet() { return Collections.newSetFromMap(new IdentityHashMap()); } static TreeSet litciset(String... items) { TreeSet set = caseInsensitiveSet(); for (String a : items) set.add(a); return set; } static String afterLastSpace(String s) { return s == null ? null : substring(s, s.lastIndexOf(' ') + 1); } static boolean containsIgnoreCase(Collection l, String s) { if (l != null) for (String x : l) if (eqic(x, s)) return true; return false; } static boolean containsIgnoreCase(String[] l, String s) { if (l != null) for (String x : l) if (eqic(x, s)) return true; return false; } static boolean containsIgnoreCase(String s, char c) { return indexOfIgnoreCase(s, String.valueOf(c)) >= 0; } static boolean containsIgnoreCase(String a, String b) { return indexOfIgnoreCase(a, b) >= 0; } static String dropSuffixIgnoreCase(String suffix, String s) { return ewic(s, suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static boolean ewicOneOf(String s, String... l) { if (s != null) for (String x : l) if (ewic(s, x)) return true; return false; } static Class run(String progID, String... args) { Class main = hotwire(progID); callMain(main, args); return main; } static boolean possibleMD5(String s) { return isMD5(s); } static String localSnippetTitle(String snippetID) { if (!isLocalSnippetID(snippetID)) return null; File f = localSnippetFile(snippetID); if (!f.exists()) return null; return or2(getFileInfoField(dropExtension(f), "Title"), "Unnamed"); } static String muricaCredentialsQuery() { return htmlQuery(muricaCredentials()); } static boolean isGeneralFileServerSnippet(long id) { return id >= 1400000 && id < 1500000; } static String standardCredentials_noCookies() { return standardCredentials() + "&noCookies=1"; } static boolean saveTextFileIfChanged(File f, String contents) { return saveTextFileIfDifferent(f, contents); } static File snippetTitle_cacheFile(String snippetID) { return javaxCachesDir("Snippet Titles/" + psI(snippetID)); } static AutoCloseable tempSetTL(ThreadLocal tl, A a) { return tempSetThreadLocal(tl, a); } static TimeZone getTimeZone(String name) { return TimeZone.getTimeZone(name); } static String standardTimeZone_name = "Europe/Berlin"; static String standardTimeZone() { return standardTimeZone_name; } static String asString(Object o) { return o == null ? null : o.toString(); } static Map> parse3_cachedInput_cache = synchronizedMRUCache(1000); static List parse3_cachedInput(String s) { List tok = parse3_cachedInput_cache.get(s); if (tok == null) parse3_cachedInput_cache.put(s, tok = parse3(s)); return tok; } static Map> parse3_cachedPattern_cache = synchronizedMRUCache(1000); static synchronized List parse3_cachedPattern(String s) { List tok = parse3_cachedPattern_cache.get(s); if (tok == null) parse3_cachedPattern_cache.put(s, tok = parse3(s)); return tok; } // match2 matches multiple "*" (matches a single token) wildcards and zero or one "..." wildcards (matches multiple tokens) static String[] match2(List pat, List tok) { // standard case (no ...) int i = pat.indexOf("..."); if (i < 0) return match2_match(pat, tok); // We're modifying it, so copy first pat = new ArrayList(pat); pat.set(i, "*"); while (pat.size() < tok.size()) { pat.add(i, "*"); // doesn't matter pat.add(i + 1, ""); } return match2_match(pat, tok); } static String[] match2_match(List pat, List tok) { List result = new ArrayList(); if (pat.size() != tok.size()) { return null; } for (int i = 1; i < pat.size(); i += 2) { String p = pat.get(i), t = tok.get(i); if (eq(p, "*")) result.add(t); else if (// bold change - match quoted and unquoted now. TODO: should remove !equalsIgnoreCase(unquote(p), unquote(t))) return null; } return result.toArray(new String[result.size()]); } static String joinSubList(List l, int i, int j) { return join(subList(l, i, j)); } static String joinSubList(List l, int i) { return join(subList(l, i)); } static String format(String pat, Object... args) { return format3(pat, args); } static boolean match(String pat, String s) { return match3(pat, s); } static boolean match(String pat, String s, Matches matches) { return match3(pat, s, matches); } static boolean match(String pat, List toks, Matches matches) { return match3(pat, toks, matches); } static String getString(Map map, Object key) { return map == null ? null : (String) map.get(key); } static String getString(List l, int idx) { return (String) get(l, idx); } static String getString(Object o, Object key) { if (o instanceof Map) return getString((Map) o, key); if (key instanceof String) return (String) getOpt(o, (String) key); throw fail("Not a string key: " + getClassName(key)); } static String getString(String key, Object o) { return getString(o, (Object) key); } static String ok2(String s) { return "ok " + s; } // An "Android" is a program that accepts text questions (on console or TCP) and outputs one response text per question // please include function myJavaSource. // for getting my known commands // disable all android making static boolean makeAndroid3_disable = false; static class Android3 implements AutoCloseable { String greeting; // optionally set this in client boolean publicOverride = false; // optionally set this in client int startPort = 5000; Responder responder; boolean console = true; // no messages on console boolean quiet = false; boolean daemon = false; boolean incomingSilent = false; int incomingPrintLimit = 200; boolean useMultiPort = true; boolean recordHistory = false; boolean verbose = false; int answerPrintLimit = 500; boolean newLineAboveAnswer, newLineBelowAnswer; // set by system int port; long vport; DialogHandler handler; ServerSocket server; Android3(String greeting) { this.greeting = greeting; } Android3() { } public void close() { dispose(); } synchronized void dispose() { if (server != null) { try { server.close(); } catch (IOException e) { print("[internal] " + e); } server = null; } if (vport != 0) { try { print("Disposing " + this); removeFromMultiPort(vport); vport = 0; } catch (Throwable __e) { _handleException(__e); } } } public String toString() { return "Bot: " + greeting + " [vport " + vport + "]"; } } static abstract class Responder { abstract String answer(String s, List history); } static Android3 makeAndroid3(final String greeting) { return makeAndroid3(new Android3(greeting)); } static Android3 makeAndroid3(final String greeting, Responder responder) { Android3 android = new Android3(greeting); android.responder = responder; return makeAndroid3(android); } static Android3 makeAndroid3(final Android3 a) { if (makeAndroid3_disable) return a; if (a.responder == null) a.responder = new Responder() { String answer(String s, List history) { return callStaticAnswerMethod(s, history); } }; if (!a.quiet) print("[bot] " + a.greeting); if (a.console && (readLine_noReadLine || makeAndroid3_consoleInUse())) a.console = false; record(a); if (a.useMultiPort) a.vport = addToMultiPort(a.greeting, makeAndroid3_verboseResponder(a)); if (a.console) makeAndroid3_handleConsole(a); if (a.useMultiPort) return a; a.handler = makeAndroid3_makeDialogHandler(a); if (a.quiet) startDialogServer_quiet.set(true); try { a.port = a.daemon ? startDialogServerOnPortAboveDaemon(a.startPort, a.handler) : startDialogServerOnPortAbove(a.startPort, a.handler); } finally { startDialogServer_quiet.set(null); } a.server = startDialogServer_serverSocket; return a; } static void makeAndroid3_handleConsole(final Android3 a) { // Console handling stuff if (!a.quiet) print("You may also type on this console."); { startThread(new Runnable() { public void run() { try { List history = new ArrayList(); while (licensed()) { String line; try { line = readLine(); } catch (Throwable e) { print(getInnerMessage(e)); break; } if (line == null) break; /*if (eq(line, "bye")) { print("> bye stranger"); history = new ArrayList(); } else*/ { history.add(line); // prints answer on console too history.add(makeAndroid3_getAnswer(line, history, a)); } } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "List history = new ArrayList();\r\n while (licensed()) {\r\n Stri..."; } }); } } static DialogHandler makeAndroid3_makeDialogHandler(final Android3 a) { return new DialogHandler() { public void run(final DialogIO io) { if (!a.publicOverride && !(publicCommOn() || io.isLocalConnection())) { io.sendLine("Sorry, not allowed"); return; } String dialogID = randomID(8); io.sendLine(a.greeting + " / Your ID: " + dialogID); List history = new ArrayList(); while (io.isStillConnected()) { if (io.waitForLine()) { final String line = io.readLineNoBlock(); String s = dialogID + " at " + now() + ": " + quote(line); if (!a.incomingSilent) print(shorten(s, a.incomingPrintLimit)); if (eq(line, "bye")) { io.sendLine("bye stranger"); return; } Matches m = new Matches(); if (a.recordHistory) history.add(line); String answer; if (match3("this is a continuation of talk *", s, m) || match3("hello bot! this is a continuation of talk *", s, m)) { dialogID = unquote(m.m[0]); answer = "ok"; } else try { makeAndroid3_io.set(io); answer = makeAndroid3_getAnswer(line, history, a); } finally { makeAndroid3_io.set(null); } if (a.recordHistory) history.add(answer); io.sendLine(answer); // appendToLog(logFile, s); } } } }; } static String makeAndroid3_getAnswer(String line, List history, Android3 a) { String answer, originalAnswer; try { originalAnswer = a.responder.answer(line, history); answer = makeAndroid3_fallback(line, history, originalAnswer); } catch (Throwable e) { e = getInnerException(e); printStackTrace(e); originalAnswer = answer = e.toString(); } if (!a.incomingSilent) { if (originalAnswer == null) originalAnswer = "?"; if (a.newLineAboveAnswer) print(); print(">" + dropFirst(indentx(2, shorten(rtrim(originalAnswer), a.answerPrintLimit)))); if (a.newLineBelowAnswer) print(); } return answer; } static String makeAndroid3_fallback(String s, List history, String answer) { // Now we only do the safe thing instead of VM inspection - give out our process ID if (answer == null && match3("what is your pid", s)) return getPID(); if (// should be fairly safe, right? answer == null && match3("what is your program id", s)) return getProgramID(); if (match3("get injection id", s)) return getInjectionID(); if (answer == null) answer = "?"; if (answer.indexOf('\n') >= 0 || answer.indexOf('\r') >= 0) answer = quote(answer); return answer; } static boolean makeAndroid3_consoleInUse() { if (isTrue(vm_generalMap_get("consoleInUse"))) return true; for (Object o : record_list) if (o instanceof Android3 && ((Android3) o).console) return true; return false; } static Responder makeAndroid3_verboseResponder(final Android3 a) { return new Responder() { String answer(String s, List history) { if (a.verbose) print("> " + shorten(s, a.incomingPrintLimit)); String answer = a.responder.answer(s, history); if (a.verbose) print("< " + shorten(answer, a.incomingPrintLimit)); return answer; } }; } static ThreadLocal makeAndroid3_io = new ThreadLocal(); static Android3 makeAndroid3() { return makeAndroid3(getProgramTitle() + "."); } static String makeResponder_callAnswerMethod(Object bot, String s, List history) { String answer = (String) callOpt(bot, "answer", s, history); if (answer == null) answer = (String) callOpt(bot, "answer", s); return answer; } static Responder makeResponder(final Object bot) { if (bot instanceof Responder) return (Responder) bot; if (bot instanceof String) { String f = (String) bot; return new Responder() { String answer(String s, List history) { String answer = (String) callOptMC((String) bot, s, history); if (answer == null) answer = (String) callOptMC((String) bot, s); return answer; } }; } return new Responder() { String answer(String s, List history) { return makeResponder_callAnswerMethod(bot, s, history); } }; } static String defaultBotName() { return getProgramTitle() + "."; } static Object rcurry(final Object f, final Object arg) { int n = numberOfFunctionArguments(f); if (n == 0) throw fail("function takes no arguments"); if (n == 1) return new F0() { Object get() { return callF(f, arg); } }; if (n == 2) return new F1() { Object get(Object a) { return callF(f, a, arg); } }; throw todo("currying a function with " + n + "arguments"); } static int cmp(Number a, Number b) { return a == null ? b == null ? 0 : -1 : cmp(a.doubleValue(), b.doubleValue()); } static int cmp(double a, double b) { return a < b ? -1 : a == b ? 0 : 1; } static int cmp(int a, int b) { return a < b ? -1 : a == b ? 0 : 1; } static int cmp(long a, long b) { return a < b ? -1 : a == b ? 0 : 1; } static int cmp(Object a, Object b) { if (a == null) return b == null ? 0 : -1; if (b == null) return 1; return ((Comparable) a).compareTo(b); } static String quoteIfNotIdentifierOrInteger(String s) { if (s == null) return null; return isJavaIdentifier(s) || isInteger(s) ? s : quote(s); } static File muricaPasswordFile() { return new File(javaxSecretDir(), "murica/muricaPasswordFile"); } static int roundDownTo(int n, int x) { return x / n * n; } static long roundDownTo(long n, long x) { return x / n * n; } static boolean substanceLookAndFeelEnabled() { return startsWith(getLookAndFeel(), "org.pushingpixels."); } static JComponent getTitlePaneComponent(RootPaneContainer window) { if (window instanceof JInternalFrame) return getInternalFrameTitlePaneComponent((JInternalFrame) window); if (!substanceLookAndFeelEnabled() || window == null) return null; JRootPane rootPane = window.getRootPane(); if (rootPane != null) { Object /*SubstanceRootPaneUI*/ ui = rootPane.getUI(); return (JComponent) call(ui, "getTitlePane"); } return null; } static A listGet(List l, int idx) { return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null; } static Method findMethod(Object o, String method, Object... args) { return findMethod_cached(o, method, args); } static boolean findMethod_checkArgs(Method m, Object[] args, boolean debug) { Class[] types = m.getParameterTypes(); if (types.length != args.length) { if (debug) System.out.println("Bad parameter length: " + args.length + " vs " + types.length); return false; } for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) { if (debug) System.out.println("Bad parameter " + i + ": " + args[i] + " vs " + types[i]); return false; } return true; } static List dropFirstAndLast(int n, List l) { return cloneSubList(l, n, l(l) - n); } static List dropFirstAndLast(int m, int n, List l) { return cloneSubList(l, m, l(l) - n); } static List dropFirstAndLast(List l) { return dropFirstAndLast(1, l); } static String dropFirstAndLast(String s) { return substring(s, 1, l(s) - 1); } static boolean regionMatches(String a, int offsetA, String b, int offsetB, int len) { return a != null && b != null && a.regionMatches(offsetA, b, offsetB, len); } static boolean regionMatches(String a, int offsetA, String b) { return regionMatches(a, offsetA, b, 0, l(b)); } static String javaTok_substringN(String s, int i, int j) { if (i == j) return ""; if (j == i + 1 && s.charAt(i) == ' ') return " "; return s.substring(i, j); } static String javaTok_substringC(String s, int i, int j) { return s.substring(i, j); } static List javaTokWithExisting(String s, List existing) { ++javaTok_n; int nExisting = javaTok_opt && existing != null ? existing.size() : 0; ArrayList tok = existing != null ? new ArrayList(nExisting) : new ArrayList(); int l = s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringN(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); // scan for non-whitespace // Special JavaX syntax: 'identifier if (c == '\'' && Character.isJavaIdentifierStart(d) && i + 2 < l && "'\\".indexOf(s.charAt(i + 2)) < 0) { j += 2; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))) ++j; } else if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { if (s.charAt(j) == opener) /*|| s.charAt(j) == '\n'*/ { // allow multi-line strings ++j; break; } else if (s.charAt(j) == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) // for stuff like "don't" do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); // Long constants like 1L if (j < l && s.charAt(j) == 'L') ++j; } else if (c == '[' && d == '[') { do ++j; while (j + 1 < l && !s.substring(j, j + 2).equals("]]")); j = Math.min(j + 2, l); } else if (c == '[' && d == '=' && i + 2 < l && s.charAt(i + 2) == '[') { do ++j; while (j + 2 < l && !s.substring(j, j + 3).equals("]=]")); j = Math.min(j + 3, l); } else ++j; if (n < nExisting && javaTokWithExisting_isCopyable(existing.get(n), s, i, j)) tok.add(existing.get(n)); else tok.add(javaTok_substringC(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); javaTok_elements += tok.size(); return tok; } static boolean javaTokWithExisting_isCopyable(String t, String s, int i, int j) { return t.length() == j - i && // << could be left out, but that's brave s.regionMatches(i, t, 0, j - i); } // i must point at the (possibly imaginary) opening bracket // index returned is index of closing bracket + 1 static int findEndOfCurlyBracketPart(List cnc, int i) { int j = i + 2, level = 1; while (j < cnc.size()) { if (eq(cnc.get(j), "{")) ++level; else if (eq(cnc.get(j), "}")) --level; if (level == 0) return j + 1; ++j; } return cnc.size(); } static Object findComponentPopupMenuListener_gen(final JComponent c) { return c == null ? null : swing(new F0() { public Object get() { try { return firstWithClassShortNamed("componentPopupMenu_Adapter", c.getMouseListeners()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret firstWithClassShortNamed('componentPopupMenu_Adapter, c.getMouseListeners..."; } }); } static boolean internalFrameActive(Component c) { final JInternalFrame f = getInternalFrame(c); return f != null && swing(new F0() { public Boolean get() { try { return f.isSelected(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret f.isSelected();"; } }); } static boolean byteArrayStartsWith(byte[] a, byte[] b) { if (a == null || b == null) return false; if (a.length < b.length) return false; for (int i = 0; i < b.length; i++) if (a[i] != b[i]) return false; return true; } static byte[] loadBeginningOfBinaryFile(File file, int maxBytes) { return loadBinaryFilePart(file, 0, maxBytes); } static ThreadLocal assertVerbose_value = new ThreadLocal(); static void assertVerbose(boolean b) { assertVerbose_value.set(b); } static boolean assertVerbose() { return isTrue(assertVerbose_value.get()); } static A liftLast(List l) { if (empty(l)) return null; int i = l(l) - 1; A a = l.get(i); l.remove(i); return a; } static List liftLast(int n, List l) { int i = l(l) - n; List part = cloneSubList(l, i); removeSubList(l, i); return part; } static Class actualMC() { return or((Class) realMC(), mc()); } static byte[] boolArrayToBytes(boolean[] a) { byte[] b = new byte[(l(a) + 7) / 8]; for (int i = 0; i < l(a); i++) if (a[i]) b[i / 8] |= 1 << (i & 7); return b; } static List> mapPairB(final Object f, Iterable> l) { return map(l, new F1, Pair>() { public Pair get(Pair p) { try { return p == null ? null : pair(p.a, (C) callF(f, p.b)); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "p == null ? null : pair(p.a, (C) callF(f, p.b))"; } }); } static List> mapPairB(final F1 f, Iterable> l) { return mapPairB((Object) f, l); } static List> mapPairB(final IF1 f, Iterable> l) { return mapPairB((Object) f, l); } static List> mapPairB(Iterable> l, IF1 f) { return mapPairB((Object) f, l); } static Pair mapPairB(IF1 f, Pair p) { return pairMapB(f, p); } static Pair mapPairB(Pair p, IF1 f) { return pairMapB(f, p); } static boolean isDigit(char c) { return Character.isDigit(c); } static String quickSubstring(String s, int i, int j) { if (i == j) return ""; return s.substring(i, j); } static Object safeUnstructure(String s) { return unstructure(s, true); } static Class getOuterClass(Class c) { return getOuterClass(c, null); } static Class getOuterClass(Class c, Object classFinder) { try { String s = c.getName(); int i = s.lastIndexOf('$'); String name = substring(s, 0, i); if (classFinder != null) return (Class) callF(classFinder, name); return Class.forName(name); } catch (Exception __e) { throw rethrow(__e); } } static HashMap instanceFieldsMap(Object o) { Class c = o.getClass(); HashMap map; synchronized (getOpt_cache) { map = getOpt_cache.get(c); if (map == null) map = getOpt_makeCache(c); } return map; } static Map thisDollarOneFields_cache = newDangerousWeakHashMap(); static Field[] thisDollarOneFields(Class c) { synchronized (thisDollarOneFields_cache) { Field[] l = thisDollarOneFields_cache.get(c); if (l == null) thisDollarOneFields_cache.put(c, l = thisDollarOneFields_uncached(c)); return l; } } static Field[] thisDollarOneFields_uncached(Class c) { List fields = new ArrayList(); do { for (Field f : c.getDeclaredFields()) if (f.getName().startsWith("this$")) fields.add(makeAccessible(f)); c = c.getSuperclass(); } while (c != null); return toArray(new Field[l(fields)], fields); } static Map> callOpt_noArgs_cache = newDangerousWeakHashMap(); static Object callOpt_noArgs(Object o, String method) { try { if (o == null) return null; if (o instanceof Class) // not optimized return callOpt(o, method); Class c = o.getClass(); HashMap map; synchronized (callOpt_noArgs_cache) { map = callOpt_noArgs_cache.get(c); if (map == null) map = callOpt_noArgs_makeCache(c); } Method m = map.get(method); return m != null ? m.invoke(o) : null; } catch (Exception __e) { throw rethrow(__e); } } // used internally - we are in synchronized block static HashMap callOpt_noArgs_makeCache(Class c) { HashMap map = new HashMap(); Class _c = c; do { for (Method m : c.getDeclaredMethods()) if (m.getParameterTypes().length == 0 && !reflection_isForbiddenMethod(m)) { makeAccessible(m); String name = m.getName(); if (!map.containsKey(name)) map.put(name, m); } _c = _c.getSuperclass(); } while (_c != null); callOpt_noArgs_cache.put(c, map); return map; } static TreeSet caseInsensitiveSet() { return caseInsensitiveSet_treeSet(); } static TreeSet caseInsensitiveSet(Collection c) { return caseInsensitiveSet_treeSet(c); } static A last(List l) { return empty(l) ? null : l.get(l.size() - 1); } static char last(String s) { return empty(s) ? '#' : s.charAt(l(s) - 1); } static int last(int[] a) { return l(a) != 0 ? a[l(a) - 1] : 0; } static double last(double[] a) { return l(a) != 0 ? a[l(a) - 1] : 0; } static A last(A[] a) { return l(a) != 0 ? a[l(a) - 1] : null; } static A last(Iterator it) { A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static A last(Collection l) { if (l == null) return null; if (l instanceof List) return (A) last(((List) l)); if (l instanceof SortedSet) return (A) last(((SortedSet) l)); Iterator it = iterator(l); A a = null; while (it.hasNext()) { ping(); a = it.next(); } return a; } static A last(SortedSet l) { return l == null ? null : l.last(); } static int or0(Integer i) { return i == null ? 0 : i; } static long or0(Long l) { return l == null ? 0L : l; } static double or0(Double d) { return d == null ? 0.0 : d; } static Object evalInNewThread(final Object f) { final Flag flag = new Flag(); final Var var = new Var(); final Var exception = new Var(); { startThread(new Runnable() { public void run() { try { try { var.set(callF(f)); } catch (Throwable e) { exception.set(e); } flag.raise(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "try {\r\n var.set(callF(f));\r\n } catch (Throwable e) {\r\n exception..."; } }); } flag.waitUntilUp(); if (exception.has()) throw rethrow(exception.get()); return var.get(); } static String callStaticAnswerMethod(List bots, String s) { for (Object c : bots) try { String answer = callStaticAnswerMethod(c, s); if (!empty(answer)) return answer; } catch (Throwable e) { print("Error calling " + getProgramID(c)); e.printStackTrace(); } return null; } static String callStaticAnswerMethod(Object c, String s) { String answer = (String) callOpt(c, "answer", s, litlist(s)); if (answer == null) answer = (String) callOpt(c, "answer", s); return emptyToNull(answer); } static String callStaticAnswerMethod(String s) { return callStaticAnswerMethod(mc(), s); } static String callStaticAnswerMethod(String s, List history) { return callStaticAnswerMethod(mc(), s, history); } static String callStaticAnswerMethod(Object c, String s, List history) { String answer = (String) callOpt(c, "answer", s, history); if (answer == null) answer = (String) callOpt(c, "answer", s); return emptyToNull(answer); } static List cloneSubList(List l, int startIndex, int endIndex) { return newSubList(l, startIndex, endIndex); } static List cloneSubList(List l, int startIndex) { return newSubList(l, startIndex); } static void removeSubList(List l, int from, int to) { if (l != null) subList(l, from, to).clear(); } static void removeSubList(List l, int from) { if (l != null) subList(l, from).clear(); } static File computerIDFile() { return javaxDataDir("Basic Info/computer-id.txt"); } static String makeRandomID(int length) { return makeRandomID(length, defaultRandomGenerator()); } static String makeRandomID(int length, Random random) { char[] id = new char[length]; for (int i = 0; i < id.length; i++) id[i] = (char) ((int) 'a' + random.nextInt(26)); return new String(id); } static String makeRandomID(Random r, int length) { return makeRandomID(length, r); } static String joinStrings(String sep, Object... strings) { return joinStrings(sep, Arrays.asList(strings)); } static String joinStrings(String sep, Iterable strings) { StringBuilder buf = new StringBuilder(); for (Object o : unnull(strings)) { String s = strOrNull(o); if (nempty(s)) { if (nempty(buf)) buf.append(sep); buf.append(s); } } return str(buf); } static String utf8streamToString(InputStream in) { return readerToString(utf8bufferedReader(in)); } static Iterator iterator(Iterable c) { return c == null ? emptyIterator() : c.iterator(); } static String htmlencode_forParams_v2(String s) { if (s == null) return ""; StringBuilder out = new StringBuilder(Math.max(16, s.length())); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c > 127 || c == '"' || c == '<' || c == '>' || c == '&') { out.append("&#"); out.append((int) c); out.append(';'); } else out.append(c); } return out.toString(); } static List codeTokensOnly(List tok) { int n = l(tok); List l = emptyList(n / 2); for (int i = 1; i < n; i += 2) l.add(tok.get(i)); return l; } // syntax 1: replace all occurrences of x in l with y static List replaceSublist(List l, List x, List y) { if (x == null) return l; int i = 0; while (true) { i = indexOfSubList(l, x, i); if (i < 0) break; replaceSublist(l, i, i + l(x), y); i += l(y); } return l; } // syntax 2: splice l at fromIndex-toIndex and replace middle part with y static List replaceSublist(List l, int fromIndex, int toIndex, List y) { int n = y.size(), toIndex_new = fromIndex + n; if (toIndex_new < toIndex) { removeSubList(l, toIndex_new, toIndex); copyListPart(y, 0, l, fromIndex, n); } else { copyListPart(y, 0, l, fromIndex, toIndex - fromIndex); if (toIndex_new > toIndex) l.addAll(toIndex, subList(y, toIndex - fromIndex)); } return l; } static A printStructure(String prefix, A o) { if (endsWithLetter(prefix)) prefix += ": "; print(prefix + structureForUser(o)); return o; } static A printStructure(A o) { print(structureForUser(o)); return o; } static String htmldecode(final String input) { if (input == null) return null; final int MIN_ESCAPE = 2; final int MAX_ESCAPE = 6; StringWriter writer = null; int len = input.length(); int i = 1; int st = 0; while (true) { // look for '&' while (i < len && input.charAt(i - 1) != '&') i++; if (i >= len) break; // found '&', look for ';' int j = i; while (j < len && j < i + MAX_ESCAPE + 1 && input.charAt(j) != ';') j++; if (j == len || j < i + MIN_ESCAPE || j == i + MAX_ESCAPE + 1) { i++; continue; } // found escape if (input.charAt(i) == '#') { // numeric escape int k = i + 1; int radix = 10; final char firstChar = input.charAt(k); if (firstChar == 'x' || firstChar == 'X') { k++; radix = 16; } try { int entityValue = Integer.parseInt(input.substring(k, j), radix); if (writer == null) writer = new StringWriter(input.length()); writer.append(input.substring(st, i - 1)); if (entityValue > 0xFFFF) { final char[] chrs = Character.toChars(entityValue); writer.write(chrs[0]); writer.write(chrs[1]); } else { writer.write(entityValue); } } catch (NumberFormatException ex) { i++; continue; } } else { // named escape CharSequence value = htmldecode_lookupMap.get(input.substring(i, j)); if (value == null) { i++; continue; } if (writer == null) writer = new StringWriter(input.length()); writer.append(input.substring(st, i - 1)); writer.append(value); } // skip escape st = j + 1; i = st; } if (writer != null) { writer.append(input.substring(st, len)); return writer.toString(); } return input; } private static final String[][] htmldecode_ESCAPES = { // " - double-quote { "\"", "quot" }, // & - ampersand { "&", "amp" }, // < - less-than { "<", "lt" }, // > - greater-than { ">", "gt" }, // Mapping to escape ISO-8859-1 characters to their named HTML 3.x equivalents. // non-breaking space { "\u00A0", "nbsp" }, // inverted exclamation mark { "\u00A1", "iexcl" }, // cent sign { "\u00A2", "cent" }, // pound sign { "\u00A3", "pound" }, // currency sign { "\u00A4", "curren" }, // yen sign = yuan sign { "\u00A5", "yen" }, // broken bar = broken vertical bar { "\u00A6", "brvbar" }, // section sign { "\u00A7", "sect" }, // diaeresis = spacing diaeresis { "\u00A8", "uml" }, // copyright sign { "\u00A9", "copy" }, // feminine ordinal indicator { "\u00AA", "ordf" }, // left-pointing double angle quotation mark = left pointing guillemet { "\u00AB", "laquo" }, // not sign { "\u00AC", "not" }, // soft hyphen = discretionary hyphen { "\u00AD", "shy" }, // registered trademark sign { "\u00AE", "reg" }, // macron = spacing macron = overline = APL overbar { "\u00AF", "macr" }, // degree sign { "\u00B0", "deg" }, // plus-minus sign = plus-or-minus sign { "\u00B1", "plusmn" }, // superscript two = superscript digit two = squared { "\u00B2", "sup2" }, // superscript three = superscript digit three = cubed { "\u00B3", "sup3" }, // acute accent = spacing acute { "\u00B4", "acute" }, // micro sign { "\u00B5", "micro" }, // pilcrow sign = paragraph sign { "\u00B6", "para" }, // middle dot = Georgian comma = Greek middle dot { "\u00B7", "middot" }, // cedilla = spacing cedilla { "\u00B8", "cedil" }, // superscript one = superscript digit one { "\u00B9", "sup1" }, // masculine ordinal indicator { "\u00BA", "ordm" }, // right-pointing double angle quotation mark = right pointing guillemet { "\u00BB", "raquo" }, // vulgar fraction one quarter = fraction one quarter { "\u00BC", "frac14" }, // vulgar fraction one half = fraction one half { "\u00BD", "frac12" }, // vulgar fraction three quarters = fraction three quarters { "\u00BE", "frac34" }, // inverted question mark = turned question mark { "\u00BF", "iquest" }, // ? - uppercase A, grave accent { "\u00C0", "Agrave" }, // ? - uppercase A, acute accent { "\u00C1", "Aacute" }, // ? - uppercase A, circumflex accent { "\u00C2", "Acirc" }, // ? - uppercase A, tilde { "\u00C3", "Atilde" }, // ? - uppercase A, umlaut { "\u00C4", "Auml" }, // ? - uppercase A, ring { "\u00C5", "Aring" }, // ? - uppercase AE { "\u00C6", "AElig" }, // ? - uppercase C, cedilla { "\u00C7", "Ccedil" }, // ? - uppercase E, grave accent { "\u00C8", "Egrave" }, // ? - uppercase E, acute accent { "\u00C9", "Eacute" }, // ? - uppercase E, circumflex accent { "\u00CA", "Ecirc" }, // ? - uppercase E, umlaut { "\u00CB", "Euml" }, // ? - uppercase I, grave accent { "\u00CC", "Igrave" }, // ? - uppercase I, acute accent { "\u00CD", "Iacute" }, // ? - uppercase I, circumflex accent { "\u00CE", "Icirc" }, // ? - uppercase I, umlaut { "\u00CF", "Iuml" }, // ? - uppercase Eth, Icelandic { "\u00D0", "ETH" }, // ? - uppercase N, tilde { "\u00D1", "Ntilde" }, // ? - uppercase O, grave accent { "\u00D2", "Ograve" }, // ? - uppercase O, acute accent { "\u00D3", "Oacute" }, // ? - uppercase O, circumflex accent { "\u00D4", "Ocirc" }, // ? - uppercase O, tilde { "\u00D5", "Otilde" }, // ? - uppercase O, umlaut { "\u00D6", "Ouml" }, // multiplication sign { "\u00D7", "times" }, // ? - uppercase O, slash { "\u00D8", "Oslash" }, // ? - uppercase U, grave accent { "\u00D9", "Ugrave" }, // ? - uppercase U, acute accent { "\u00DA", "Uacute" }, // ? - uppercase U, circumflex accent { "\u00DB", "Ucirc" }, // ? - uppercase U, umlaut { "\u00DC", "Uuml" }, // ? - uppercase Y, acute accent { "\u00DD", "Yacute" }, // ? - uppercase THORN, Icelandic { "\u00DE", "THORN" }, // ? - lowercase sharps, German { "\u00DF", "szlig" }, // ? - lowercase a, grave accent { "\u00E0", "agrave" }, // ? - lowercase a, acute accent { "\u00E1", "aacute" }, // ? - lowercase a, circumflex accent { "\u00E2", "acirc" }, // ? - lowercase a, tilde { "\u00E3", "atilde" }, // ? - lowercase a, umlaut { "\u00E4", "auml" }, // ? - lowercase a, ring { "\u00E5", "aring" }, // ? - lowercase ae { "\u00E6", "aelig" }, // ? - lowercase c, cedilla { "\u00E7", "ccedil" }, // ? - lowercase e, grave accent { "\u00E8", "egrave" }, // ? - lowercase e, acute accent { "\u00E9", "eacute" }, // ? - lowercase e, circumflex accent { "\u00EA", "ecirc" }, // ? - lowercase e, umlaut { "\u00EB", "euml" }, // ? - lowercase i, grave accent { "\u00EC", "igrave" }, // ? - lowercase i, acute accent { "\u00ED", "iacute" }, // ? - lowercase i, circumflex accent { "\u00EE", "icirc" }, // ? - lowercase i, umlaut { "\u00EF", "iuml" }, // ? - lowercase eth, Icelandic { "\u00F0", "eth" }, // ? - lowercase n, tilde { "\u00F1", "ntilde" }, // ? - lowercase o, grave accent { "\u00F2", "ograve" }, // ? - lowercase o, acute accent { "\u00F3", "oacute" }, // ? - lowercase o, circumflex accent { "\u00F4", "ocirc" }, // ? - lowercase o, tilde { "\u00F5", "otilde" }, // ? - lowercase o, umlaut { "\u00F6", "ouml" }, // division sign { "\u00F7", "divide" }, // ? - lowercase o, slash { "\u00F8", "oslash" }, // ? - lowercase u, grave accent { "\u00F9", "ugrave" }, // ? - lowercase u, acute accent { "\u00FA", "uacute" }, // ? - lowercase u, circumflex accent { "\u00FB", "ucirc" }, // ? - lowercase u, umlaut { "\u00FC", "uuml" }, // ? - lowercase y, acute accent { "\u00FD", "yacute" }, // ? - lowercase thorn, Icelandic { "\u00FE", "thorn" }, // ? - lowercase y, umlaut { "\u00FF", "yuml" }, { "\u2013", "ndash" }, { "\u2018", "lsquo" }, { "\u2019", "rsquo" }, { "\u201D", "rdquo" }, { "\u201C", "ldquo" }, { "\u2014", "mdash" }, // the controversial (but who cares!) ' { "'", "apos" } // stackoverflow.com/questions/2083754/why-shouldnt-apos-be-used-to-escape-single-quotes }; private static final HashMap htmldecode_lookupMap; static { htmldecode_lookupMap = new HashMap(); for (final CharSequence[] seq : htmldecode_ESCAPES) htmldecode_lookupMap.put(seq[1].toString(), seq[0]); } static A[] newObjectArrayOfSameType(A[] a) { return newObjectArrayOfSameType(a, a.length); } static A[] newObjectArrayOfSameType(A[] a, int n) { return (A[]) Array.newInstance(a.getClass().getComponentType(), n); } static betterCIComparator_C betterCIComparator_instance; static betterCIComparator_C betterCIComparator() { if (betterCIComparator_instance == null) betterCIComparator_instance = new betterCIComparator_C(); return betterCIComparator_instance; } final static class betterCIComparator_C implements Comparator { public int compare(String s1, String s2) { if (s1 == null) return s2 == null ? 0 : -1; if (s2 == null) return 1; int n1 = s1.length(); int n2 = s2.length(); int min = Math.min(n1, n2); for (int i = 0; i < min; i++) { char c1 = s1.charAt(i); char c2 = s2.charAt(i); if (c1 != c2) { c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); if (c1 != c2) { c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); if (c1 != c2) { // No overflow because of numeric promotion return c1 - c2; } } } } return n1 - n2; } } static Map compileRegexpIC_cache = syncMRUCache(10); static java.util.regex.Pattern compileRegexpIC(String pat) { java.util.regex.Pattern p = compileRegexpIC_cache.get(pat); if (p == null) { try { compileRegexpIC_cache.put(pat, p = java.util.regex.Pattern.compile(pat, Pattern.CASE_INSENSITIVE)); } catch (PatternSyntaxException e) { throw rethrow(wrapPatternSyntaxException(e)); } } return p; } static Matcher regexpIC(Pattern pat, String s) { return pat.matcher(unnull(s)); } static Matcher regexpIC(String pat, String s) { return compileRegexpIC(pat).matcher(unnull(s)); } static Pattern regexpIC(String pat) { return compileRegexpIC(pat); } static boolean addIfNotNull(Collection l, A a) { return a != null && l != null & l.add(a); } static void addIfNotNull(MultiSet ms, A a) { if (a != null && ms != null) ms.add(a); } static Object get2(Object o, String field1, String field2) { return get(get(o, field1), field2); } static boolean startsWithAny(String a, Collection b) { for (String prefix : unnull(b)) if (startsWith(a, prefix)) return true; return false; } static boolean startsWithAny(String a, String... b) { if (b != null) for (String prefix : unnull(b)) if (startsWith(a, prefix)) return true; return false; } static boolean startsWithAny(String a, Collection b, Matches m) { for (String prefix : unnull(b)) if (startsWith(a, prefix, m)) return true; return false; } static String mcDollar() { return mcName() + "$"; } static String afterDollar(String s) { return substring(s, smartIndexOf(s, '$') + 1); } static File[] listFiles(File dir) { File[] files = dir.listFiles(); return files == null ? new File[0] : files; } static File[] listFiles(String dir) { return listFiles(new File(dir)); } static Class hotwireOnce(String programID) { return hotwireCached(programID, false); } static char stringToChar(String s) { if (l(s) != 1) throw fail("bad stringToChar: " + s); return firstChar(s); } static TreeSet treeSet() { return new TreeSet(); } // custom mainClass only works with hotwire_here static Class hotwire(String src) { return hotwire(src, __1 -> mainClassNameForClassLoader(__1)); } static Class hotwire(String src, IF1 calculateMainClass) { assertFalse(_inCore()); Class j = getJavaX(); if (isAndroid()) { synchronized (j) { // hopefully this goes well... List libraries = new ArrayList(); File srcDir = (File) call(j, "transpileMain", src, libraries); if (srcDir == null) throw fail("transpileMain returned null (src=" + quote(src) + ")"); Object androidContext = get(j, "androidContext"); return (Class) call(j, "loadx2android", srcDir, src); } } else { Class c = (Class) (call(j, "hotwire", src)); hotwire_copyOver(c); return c; } } static A callMain(A c, String... args) { callOpt(c, "main", new Object[] { args }); return c; } static void callMain() { callMain(mc()); } static String getFileInfoField(File f, String field) { return getOneLineFileInfoField(f, field); } static String htmlQuery(Map params) { return empty(params) ? "" : "?" + makePostData(params); } static String htmlQuery(Object... data) { return empty(data) ? "" : "?" + makePostData(data); } static Object[] muricaCredentials() { String pass = muricaPassword(); return nempty(pass) ? new Object[] { "_pass", pass } : new Object[0]; } static boolean saveTextFileIfDifferent(File f, String contents) { // TODO: optimize if (eq(loadTextFile(f), contents)) return false; { saveTextFile(f, contents); return true; } } static List parse3(String s) { return dropPunctuation(javaTokPlusPeriod(s)); } static boolean equalsIgnoreCase(String a, String b) { return eqic(a, b); } static boolean equalsIgnoreCase(char a, char b) { return eqic(a, b); } static boolean match3(String pat, String s) { return match3(pat, s, null); } static boolean match3(String pat, String s, Matches matches) { if (pat == null || s == null) return false; return match3(pat, parse3_cachedInput(s), matches); } static boolean match3(String pat, List toks, Matches matches) { List tokpat = parse3_cachedPattern(pat); return match3(tokpat, toks, matches); } static boolean match3(List tokpat, List toks, Matches matches) { String[] m = match2(tokpat, toks); // print(structure(tokpat) + " on " + structure(toks) + " => " + structure(m)); if (m == null) return false; if (matches != null) matches.m = m; return true; } static void removeFromMultiPort(long vport) { if (vport == 0) return; for (Object port : getMultiPorts()) call(port, "removePort", vport); } static List record_list = synchroList(); static void record(Object o) { record_list.add(o); } static Object addToMultiPort_responder; static long addToMultiPort(final String botName) { return addToMultiPort(botName, new Object() { public String answer(String s, List history) { String answer = (String) (callOpt(getMainClass(), "answer", s, history)); if (answer != null) return answer; answer = (String) callOpt(getMainClass(), "answer", s); if (answer != null) return answer; if (match3("get injection id", s)) return getInjectionID(); return null; } }); } static long addToMultiPort(final String botName, final Object responder) { // print(botName); addToMultiPort_responder = responder; startMultiPort(); List ports = getMultiPorts(); if (ports == null) return 0; if (ports.isEmpty()) throw fail("No multiports!"); if (ports.size() > 1) print("Multiple multi-ports. Using last one."); Object port = last(ports); Object responder2 = new Object() { public String answer(String s, List history) { if (match3("get injection id", s)) return getInjectionID(); if (match3("your name", s)) return botName; return (String) call(responder, "answer", s, history); } }; record(responder2); return (Long) call(port, "addResponder", botName, responder2); } static AtomicInteger dialogServer_clients = new AtomicInteger(); static boolean dialogServer_printConnects = false; static ThreadLocal startDialogServer_quiet = new ThreadLocal(); static Set dialogServer_knownClients = synchroTreeSet(); static int startDialogServerOnPortAbove(int port, DialogHandler handler) { while (!forbiddenPort(port) && !startDialogServerIfPortAvailable(port, handler)) ++port; return port; } static int startDialogServerOnPortAboveDaemon(int port, DialogHandler handler) { while (!forbiddenPort(port) && !startDialogServerIfPortAvailable(port, handler, true)) ++port; return port; } static void startDialogServer(int port, DialogHandler handler) { if (!startDialogServerIfPortAvailable(port, handler)) throw fail("Can't start dialog server on port " + port); } static boolean startDialogServerIfPortAvailable(int port, final DialogHandler handler) { return startDialogServerIfPortAvailable(port, handler, false); } static ServerSocket startDialogServer_serverSocket; static boolean startDialogServerIfPortAvailable(int port, final DialogHandler handler, boolean daemon) { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(port); } catch (IOException e) { // probably the port number is used - let's assume there already is a chat server. return false; } final ServerSocket _serverSocket = serverSocket; startDialogServer_serverSocket = serverSocket; Thread thread = new Thread("Socket accept port " + port) { public void run() { try { while (true) { try { final Socket s = _serverSocket.accept(); String client = s.getInetAddress().toString(); if (!dialogServer_knownClients.contains(client) && neq(client, "/127.0.0.1")) { print("connect from " + client + " - clients: " + dialogServer_clients.incrementAndGet()); dialogServer_knownClients.add(client); } String threadName = "Handling client " + s.getInetAddress(); Thread t2 = new Thread(threadName) { public void run() { try { final Writer w = new OutputStreamWriter(s.getOutputStream(), "UTF-8"); final BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8")); DialogIO io = new DialogIO() { // This should be the same as #1001076 (talkTo) boolean isLocalConnection() { return s.getInetAddress().isLoopbackAddress(); } boolean isStillConnected() { return !(eos || s.isClosed()); } void sendLine(String line) { try { w.write(line + "\n"); w.flush(); } catch (Exception __e) { throw rethrow(__e); } } String readLineImpl() { try { return in.readLine(); } catch (Exception __e) { throw rethrow(__e); } } public void close() { try { s.close(); } catch (IOException e) { // whatever } } Socket getSocket() { return s; } }; try { handler.run(io); } finally { if (!io.noClose) s.close(); } } catch (IOException e) { print("[internal] " + e); } finally { // print("client disconnect - " + dialogServer_clients.decrementAndGet() + " remaining"); } } }; // Thread t2 // ? t2.setDaemon(true); t2.start(); } catch (SocketTimeoutException e) { } } } catch (IOException e) { print("[internal] " + e); } } }; if (daemon) thread.setDaemon(true); thread.start(); if (!isTrue(getAndClearThreadLocal(startDialogServer_quiet))) print("Dialog server on port " + port + " started."); return true; } static volatile boolean readLine_noReadLine = false; static String readLine_lastInput; static String readLine_prefix = "[] "; static String readLine() { if (readLine_noReadLine) return null; String s = readLineHidden(); if (s != null) { readLine_lastInput = s; print(readLine_prefix + s); } return s; } static String getInnerMessage(Throwable e) { if (e == null) return null; return getInnerException(e).getMessage(); } static boolean publicCommOn() { return "1".equals(loadTextFile(new File(userHome(), ".javax/public-communication"))); } static int randomID_defaultLength = 12; static String randomID(int length) { return makeRandomID(length); } static String randomID(Random r, int length) { return makeRandomID(r, length); } static String randomID() { return randomID(randomID_defaultLength); } static String randomID(Random r) { return randomID(r, randomID_defaultLength); } static String indentx(String s) { return indentx(indent_default, s); } static String indentx(int n, String s) { return dropSuffix(repeat(' ', n), indent(n, s)); } static String indentx(String indent, String s) { return dropSuffix(indent, indent(indent, s)); } static String processID_cached; // try to get our current process ID static String getPID() { if (processID_cached == null) { String name = ManagementFactory.getRuntimeMXBean().getName(); processID_cached = name.replaceAll("@.*", ""); } return processID_cached; } static String getInjectionID() { return (String) call(getJavaX(), "getInjectionID", getMainClass()); } static Object callOptMC(String method, Object... args) { return callOpt(mc(), method, args); } static int numberOfFunctionArguments(Object f) { if (f instanceof F0) return 0; if (f instanceof F1) return 1; if (f instanceof VF1) return 1; if (f instanceof String) return numberOfMethodArguments(mc(), (String) f); return numberOfMethodArguments(f, "get"); } static String getLookAndFeel() { return getClassName(UIManager.getLookAndFeel()); } static JComponent getInternalFrameTitlePaneComponent(JInternalFrame f) { return (JComponent) childWithClassNameEndingWith(f, "InternalFrameTitlePane"); } static A firstWithClassShortNamed(String shortName, Iterable l) { if (l != null) for (A o : l) if (eq(shortClassName(o), shortName)) return o; return null; } static A firstWithClassShortNamed(String shortName, A[] l) { if (l != null) for (A o : l) if (eq(shortClassName(o), shortName)) return o; return null; } static byte[] loadBinaryFilePart(File file, long start, long end) { try { RandomAccessFile raf = new RandomAccessFile(file, "r"); int n = toInt(min(raf.length(), end - start)); byte[] buffer = new byte[n]; try { raf.seek(start); raf.readFully(buffer, 0, n); return buffer; } finally { raf.close(); } } catch (Exception __e) { throw rethrow(__e); } } static Object realMC() { return getThreadLocal(realMC_tl()); } static Pair pairMapB(Object f, Pair p) { return p == null ? null : pair(p.a, callF(f, p.b)); } static Pair pairMapB(IF1 f, Pair p) { return p == null ? null : pair(p.a, f.get(p.b)); } static Pair pairMapB(Pair p, Object f) { return pairMap(f, p); } static Object[] toArray(Collection c) { return toObjectArray(c); } static A[] toArray(Class type, Iterable c) { return toArray(c, type); } static A[] toArray(Iterable c, Class type) { A[] a = arrayOfType(l(c), type); if (a.length == 0) return a; asList(c).toArray(a); return a; } // array must have correct length and will be filled static A[] toArray(A[] array, Collection c) { if (array == null || c == null) return null; asList(c).toArray(array); return array; } static boolean reflection_isForbiddenMethod(Method m) { return m.getDeclaringClass() == Object.class && eqOneOf(m.getName(), "finalize", "clone", "registerNatives"); } static TreeSet caseInsensitiveSet_treeSet() { return new TreeSet(caseInsensitiveComparator()); } static TreeSet caseInsensitiveSet_treeSet(Collection c) { return toCaseInsensitiveSet_treeSet(c); } static ArrayList litlist(A... a) { ArrayList l = new ArrayList(a.length); for (A x : a) l.add(x); return l; } static String emptyToNull(String s) { return eq(s, "") ? null : s; } static Map emptyToNull(Map map) { return empty(map) ? null : map; } static Random defaultRandomGenerator() { return ThreadLocalRandom.current(); } static String readerToString(Reader r) { try { if (r == null) return null; try { StringBuilder buf = new StringBuilder(); int n = 0; while (true) { int ch = r.read(); if (ch < 0) break; buf.append((char) ch); ++n; // if ((n % loadPage_verboseness) == 0) print(" " + n + " chars read"); } return buf.toString(); } finally { r.close(); } } catch (Exception __e) { throw rethrow(__e); } } static int indexOfSubList(List x, List y) { return indexOfSubList(x, y, 0); } static int indexOfSubList(List x, List y, int i) { outer: for (; i + l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i + j), y.get(j))) continue outer; return i; } return -1; } static int indexOfSubList(List x, A[] y, int i) { outer: for (; i + l(y) <= l(x); i++) { for (int j = 0; j < l(y); j++) if (neq(x.get(i + j), y[j])) continue outer; return i; } return -1; } static void copyListPart(List a, int i1, List b, int i2, int n) { if (a == null || b == null) return; for (int i = 0; i < n; i++) b.set(i2 + i, a.get(i1 + i)); } static boolean endsWithLetter(String s) { return nempty(s) && isLetter(last(s)); } static String structureForUser(Object o) { return beautifyStructure(struct_noStringSharing(o)); } static RuntimeException wrapPatternSyntaxException(PatternSyntaxException e) { if (e == null) return null; String pat = e.getPattern(); int i = e.getIndex(); return new RuntimeException("Regular expression error between " + multiLineQuoteWithSpaces(substring(pat, 0, i)) + " and " + multiLineQuoteWithSpaces(substring(pat, i)) + " - " + e.getMessage()); } static String mcName() { return mc().getName(); } // returns l(s) if not found static int smartIndexOf(String s, String sub, int i) { if (s == null) return 0; i = s.indexOf(sub, min(i, l(s))); return i >= 0 ? i : l(s); } static int smartIndexOf(String s, int i, char c) { return smartIndexOf(s, c, i); } static int smartIndexOf(String s, char c, int i) { if (s == null) return 0; i = s.indexOf(c, min(i, l(s))); return i >= 0 ? i : l(s); } static int smartIndexOf(String s, String sub) { return smartIndexOf(s, sub, 0); } static int smartIndexOf(String s, char c) { return smartIndexOf(s, c, 0); } static int smartIndexOf(List l, A sub) { return smartIndexOf(l, sub, 0); } static int smartIndexOf(List l, int start, A sub) { return smartIndexOf(l, sub, start); } static int smartIndexOf(List l, A sub, int start) { int i = indexOf(l, sub, start); return i < 0 ? l(l) : i; } static TreeMap hotwireCached_cache = new TreeMap(); static Lock hotwireCached_lock = lock(); static Class hotwireCached(String programID) { return hotwireCached(programID, true); } static Class hotwireCached(String programID, boolean runMain) { return hotwireCached(programID, runMain, false); } static Class hotwireCached(String programID, boolean runMain, boolean dependent) { Lock __0 = hotwireCached_lock; lock(__0); try { programID = formatSnippetID(programID); Class c = hotwireCached_cache.get(programID); if (c == null) { c = hotwire(programID); if (dependent) makeDependent(c); if (runMain) callMain(c); hotwireCached_cache.put(programID, c); } return c; } finally { unlock(__0); } } static char firstChar(String s) { return s.charAt(0); } static boolean _inCore() { return false; } static List hotwire_copyOver_after = synchroList(); static void hotwire_copyOver(Class c) { // TODO: make a mechanism for making such "inheritable" fields for (String field : ll("print_log", "print_silent", "androidContext", "_userHome")) setOptIfNotNull(c, field, getOpt(mc(), field)); setOptIfNotNull(c, "mainBot", getMainBot()); setOpt(c, "creator_class", new WeakReference(mc())); pcallFAll(hotwire_copyOver_after, c); } static String getOneLineFileInfoField(File f, String field) { File infoFile = associatedInfosFile(f); List lines = lines(loadTextFile(infoFile)); return firstStartingWithIC_drop(lines, field + ": "); } static String makePostData(Map map) { StringBuilder buf = new StringBuilder(); for (Map.Entry e : map.entrySet()) { String key = (String) (e.getKey()); Object val = e.getValue(); if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode(/*escapeMultichars*/ (value))); } } return str(buf); } static String makePostData(Object... params) { StringBuilder buf = new StringBuilder(); int n = l(params); for (int i = 0; i + 1 < n; i += 2) { String key = (String) (params[i]); Object val = params[i + 1]; if (val != null) { String value = str(val); if (nempty(buf)) buf.append("&"); buf.append(urlencode(key)).append("=").append(urlencode(/*escapeMultichars*/ (value))); } } return str(buf); } static List dropPunctuation_keep = ll("*", "<", ">"); static List dropPunctuation(List tok) { tok = new ArrayList(tok); for (int i = 1; i < tok.size(); i += 2) { String t = tok.get(i); if (t.length() == 1 && !Character.isLetter(t.charAt(0)) && !Character.isDigit(t.charAt(0)) && !dropPunctuation_keep.contains(t)) { tok.set(i - 1, tok.get(i - 1) + tok.get(i + 1)); tok.remove(i); tok.remove(i); i -= 2; } } return tok; } static String dropPunctuation(String s) { return join(dropPunctuation(nlTok(s))); } static List getMultiPorts() { return (List) callOpt(getJavaX(), "getMultiPorts"); } // start multi-port if none exists in current VM. static void startMultiPort() { List mp = getMultiPorts(); if (mp != null && mp.isEmpty()) { nohupJavax("#1001639"); throw fail("Upgrading JavaX, please restart this program afterwards."); // callMain(hotwire("#1001672")); } } static Set synchroTreeSet() { return Collections.synchronizedSet(new TreeSet()); } static Set synchroTreeSet(TreeSet set) { return Collections.synchronizedSet(set); } static boolean forbiddenPort(int port) { // adb return port == 5037; } static String readLineHidden() { try { if (get(javax(), "readLine_reader") == null) set(javax(), "readLine_reader", new BufferedReader(new InputStreamReader(System.in, "UTF-8"))); try { return ((BufferedReader) get(javax(), "readLine_reader")).readLine(); } finally { consoleClearInput(); } } catch (Exception __e) { throw rethrow(__e); } } static int indent_default = 2; static String indent(int indent) { return repeat(' ', indent); } static String indent(int indent, String s) { return indent(repeat(' ', indent), s); } static String indent(String indent, String s) { return indent + s.replace("\n", "\n" + indent); } static String indent(String s) { return indent(indent_default, s); } static List indent(String indent, List lines) { List l = new ArrayList(); if (lines != null) for (String s : lines) l.add(indent + s); return l; } static int numberOfMethodArguments(Object o, String method) { Class c; boolean mustBeStatic = false; if (o instanceof Class) { c = (Class) o; mustBeStatic = true; } else c = o.getClass(); Class _c = c; int n = -1; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (!m.getName().equals(method)) continue; if (mustBeStatic && !methodIsStatic(m)) continue; int nn = l(m.getParameterTypes()); if (n == -1) n = nn; else if (n != nn) throw fail("Variable number of method arguments: " + _c + "." + method); } c = c.getSuperclass(); } if (n == -1) throw fail("Method not found: " + _c + "." + method); return n; } static Component childWithClassNameEndingWith(Component c, String suffix) { if (endsWith(className(c), suffix)) return c; Component x; for (Component comp : getComponents(c)) if ((x = childWithClassNameEndingWith(comp, suffix)) != null) return x; return null; } static ThreadLocal realMC_tl_tl = new ThreadLocal(); static ThreadLocal realMC_tl() { return realMC_tl_tl; } static Pair pairMap(Object f, Pair p) { return p == null ? null : pair(callF(f, p.a), callF(f, p.b)); } static Pair pairMap(IF1 f, Pair p) { return p == null ? null : pair(callF(f, p.a), callF(f, p.b)); } static Pair pairMap(Pair p, Object f) { return pairMap(f, p); } static TreeSet toCaseInsensitiveSet_treeSet(Iterable c) { if (isCISet(c)) return (TreeSet) c; TreeSet set = caseInsensitiveSet_treeSet(); addAll(set, c); return set; } static TreeSet toCaseInsensitiveSet_treeSet(String... x) { TreeSet set = caseInsensitiveSet_treeSet(); addAll(set, x); return set; } static String beautifyStructure(String s) { List tok = javaTokForStructure(s); structure_addTokenMarkers(tok); jreplace(tok, "lhm", ""); return join(tok); } static String struct_noStringSharing(Object o) { structure_Data d = new structure_Data(); d.noStringSharing = true; return structure(o, d); } static String multiLineQuoteWithSpaces(String s) { return multiLineQuote(" " + s + " "); } static Object makeDependent_postProcess; static void makeDependent(Object c) { if (c == null) return; assertTrue("Not a class", c instanceof Class); // cleans up the list dependentClasses(); hotwire_classes.add(new WeakReference(c)); Object local_log = getOpt(mc(), "local_log"); if (local_log != null) setOpt(c, "local_log", local_log); /*if (isTrue(getOpt(c, 'ping_actions_shareable))) setOpt(c, +ping_actions);*/ Object print_byThread = getOpt(mc(), "print_byThread"); if (print_byThread != null) setOpt(c, "print_byThread", print_byThread); callF(makeDependent_postProcess, c); } static void setOptIfNotNull(Object o, String field, Object value) { if (value != null) setOpt(o, field, value); } static Object mainBot; static Object getMainBot() { return mainBot; } static File associatedInfosFile(File f) { return replaceExtension(f, ".infos"); } static String firstStartingWithIC_drop(Collection l, final String prefix) { for (String s : unnull(l)) if (swic(s, prefix)) return substring(s, l(prefix)); return null; } static String firstStartingWithIC_drop(String prefix, Collection l) { return firstStartingWithIC_drop(l, prefix); } static List nlTok(String s) { return javaTokPlusPeriod(s); } static void consoleClearInput() { consoleSetInput(""); } static List getComponents(final Component c) { return !(c instanceof Container) ? emptyList() : asList(swing(new F0() { public Component[] get() { try { return ((Container) c).getComponents(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret ((Container) c).getComponents();"; } })); } static boolean isCISet(Iterable l) { return l instanceof TreeSet && ((TreeSet) l).comparator() == caseInsensitiveComparator(); } static List javaTokForStructure(String s) { return javaTok_noMLS(s); } static String structure_addTokenMarkers(String s) { return join(structure_addTokenMarkers(javaTokForStructure(s))); } static List structure_addTokenMarkers(List tok) { // find references TreeSet refs = new TreeSet(); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (t.startsWith("t") && isInteger(t.substring(1))) refs.add(parseInt(t.substring(1))); } if (empty(refs)) return tok; // add markers for (int i : refs) { int idx = i * 2 + 1; // broken structure if (idx >= l(tok)) continue; String t = ""; if (endsWithLetterOrDigit(tok.get(idx - 1))) t = " "; tok.set(idx, t + "m" + i + " " + tok.get(idx)); } return tok; } static String jreplace(String s, String in, String out) { return jreplace(s, in, out, null); } static String jreplace(String s, String in, String out, Object condition) { List tok = javaTok(s); return jreplace(tok, in, out, condition) ? join(tok) : s; } // leaves tok properly tokenized // returns true iff anything was replaced static boolean jreplace(List tok, String in, String out) { return jreplace(tok, in, out, false, true, null); } static boolean jreplace(List tok, String in, String out, Object condition) { return jreplace(tok, in, out, false, true, condition); } static boolean jreplace(List tok, String in, String out, IF2, Integer, Boolean> condition) { return jreplace(tok, in, out, (Object) condition); } static boolean jreplace(List tok, String in, String out, boolean ignoreCase, boolean reTok, Object condition) { String[] toks = javaTokForJFind_array(in); int lTokin = toks.length * 2 + 1; boolean anyChange = false; int i = -1; for (int n = 0; n < 10000; n++) { // TODO: don't need this check anymore i = findCodeTokens(tok, i + 1, ignoreCase, toks, condition); if (i < 0) return anyChange; // N to N List subList = tok.subList(i - 1, i + lTokin - 1); String expansion = jreplaceExpandRefs(out, subList); int end = i + lTokin - 2; // C to C clearAllTokens(tok, i, end); tok.set(i, expansion); if (// would this ever be false?? reTok) reTok(tok, i, end); i = end; anyChange = true; } throw fail("woot? 10000! " + quote(in) + " => " + quote(out)); } static boolean jreplace_debug = false; static String multiLineQuote(String s) { for (int i = 0; ; i++) { String closer = "]" + rep('=', i) + "]"; if (!contains(s, closer)) return "[" + rep('=', i) + "[" + s + closer; } } static List dependentClasses() { return cleanUpAndGetWeakReferencesList(hotwire_classes); } static File replaceExtension(File f, String extOld, String extNew) { return newFile(replaceExtension(f2s(f), extOld, extNew)); } static File replaceExtension(File f, String extNew) { return replaceExtension(f, fileExtension(f), extNew); } static String replaceExtension(String s, String extOld, String extNew) { s = dropSuffixIC(addPrefixOptIfNempty(".", extOld), s); return s + addPrefixOptIfNempty(".", extNew); } static String replaceExtension(String name, String extNew) { return replaceExtension(name, fileExtension(name), extNew); } static List javaTok_noMLS(String s) { ArrayList tok = new ArrayList(); int l = s == null ? 0 : s.length(); int i = 0, n = 0; while (i < l) { int j = i; char c, d; // scan for whitespace while (j < l) { c = s.charAt(j); d = j + 1 >= l ? '\0' : s.charAt(j + 1); if (c == ' ' || c == '\t' || c == '\r' || c == '\n') ++j; else if (c == '/' && d == '*') { do ++j; while (j < l && !s.substring(j, Math.min(j + 2, l)).equals("*/")); j = Math.min(j + 2, l); } else if (c == '/' && d == '/') { do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0); } else break; } tok.add(javaTok_substringN(s, i, j)); ++n; i = j; if (i >= l) break; c = s.charAt(i); d = i + 1 >= l ? '\0' : s.charAt(i + 1); // scan for non-whitespace if (c == '\'' || c == '"') { char opener = c; ++j; while (j < l) { int c2 = s.charAt(j); if (c2 == opener || c2 == '\n' && opener == '\'') { // allow multi-line strings, but not for ' ++j; break; } else if (c2 == '\\' && j + 1 < l) j += 2; else ++j; } } else if (Character.isJavaIdentifierStart(c)) do ++j; while (j < l && Character.isJavaIdentifierPart(s.charAt(j))); else if (Character.isDigit(c)) { do ++j; while (j < l && Character.isDigit(s.charAt(j))); // Long constants like 1L if (j < l && s.charAt(j) == 'L') ++j; } else ++j; tok.add(javaTok_substringC(s, i, j)); ++n; i = j; } if ((tok.size() % 2) == 0) tok.add(""); return tok; } static Map javaTokForJFind_array_cache = synchronizedMRUCache(1000); static String[] javaTokForJFind_array(String s) { String[] tok = javaTokForJFind_array_cache.get(s); if (tok == null) javaTokForJFind_array_cache.put(s, tok = codeTokensAsStringArray(jfind_preprocess(javaTok(s)))); return tok; } static int findCodeTokens(List tok, String... tokens) { return findCodeTokens(tok, 1, false, tokens); } static int findCodeTokens(List tok, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, 1, ignoreCase, tokens); } static int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String... tokens) { return findCodeTokens(tok, startIdx, ignoreCase, tokens, null); } static HashSet findCodeTokens_specials = lithashset("*", "", "", "", "\\*"); static int findCodeTokens_bails, findCodeTokens_nonbails; static interface findCodeTokens_Matcher { boolean get(String token); } static int findCodeTokens(List tok, int startIdx, boolean ignoreCase, String[] tokens, Object condition) { int end = tok.size() - tokens.length * 2 + 2, nTokens = tokens.length; int i = startIdx | 1; // bail out early if first token not found (works great with IndexedList) String firstToken = tokens[0]; if (!ignoreCase && !findCodeTokens_specials.contains(firstToken)) { // quickly scan for first token while (i < end && !firstToken.equals(tok.get(i))) i += 2; } findCodeTokens_Matcher[] matchers = new findCodeTokens_Matcher[nTokens]; for (int j = 0; j < nTokens; j++) { String p = tokens[j]; findCodeTokens_Matcher matcher; if (p.equals("*")) matcher = t -> true; else if (p.equals("")) matcher = t -> isQuoted(t); else if (p.equals("")) matcher = t -> isIdentifier(t); else if (p.equals("")) matcher = t -> isInteger(t); else if (p.equals("\\*")) matcher = t -> t.equals("*"); else if (ignoreCase) matcher = t -> eqic(p, t); else matcher = t -> t.equals(p); matchers[j] = matcher; } outer: for (; i < end; i += 2) { for (int j = 0; j < nTokens; j++) if (!matchers[j].get(tok.get(i + j * 2))) continue outer; if (// pass N index condition == null || checkTokCondition(condition, tok, i - 1)) return i; } return -1; } // "$1" is first code token, "$2" second code token etc. static String jreplaceExpandRefs(String s, List tokref) { if (!contains(s, '$')) return s; List tok = javaTok(s); for (int i = 1; i < l(tok); i += 2) { String t = tok.get(i); if (t.startsWith("$") && isInteger(t.substring(1))) { String x = tokref.get(-1 + parseInt(t.substring(1)) * 2); tok.set(i, x); } else if (t.equals("\\")) { tok.set(i, ""); i += 2; } } return join(tok); } static void clearAllTokens(List tok) { for (int i = 0; i < tok.size(); i++) tok.set(i, ""); } static void clearAllTokens(List tok, int i, int j) { for (; i < j; i++) tok.set(i, ""); } static List reTok(List tok) { replaceCollection(tok, javaTok(tok)); return tok; } static List reTok(List tok, int i) { return reTok(tok, i, i + 1); } static List reTok(List tok, int i, int j) { // extend i to an "N" token // and j to "C" (so j-1 is an "N" token) i = max(i & ~1, 0); j = min(l(tok), j | 1); if (i >= j) return tok; List t = javaTok(joinSubList(tok, i, j)); replaceListPart(tok, i, j, t); // fallback to safety // reTok(tok); return tok; } static List> hotwire_classes = synchroList(); static Class hotwireDependent(String src) { Class c = hotwire(src); makeDependent(c); return c; } static List cleanUpAndGetWeakReferencesList(List> l) { if (l == null) return null; synchronized (l) { List out = new ArrayList(); for (int i = 0; i < l(l); i++) { A a = l.get(i).get(); if (a == null) l.remove(i--); else out.add(a); } return out; } } static String fileExtension(File f) { if (f == null) return null; return fileExtension(f.getName()); } static String fileExtension(String s) { return substring(s, smartLastIndexOf(s, '.')); } static String dropSuffixIC(String suffix, String s) { return s == null ? null : ewic(s, suffix) ? s.substring(0, l(s) - l(suffix)) : s; } static String addPrefixOptIfNempty(String prefix, String s) { return addPrefixIfNotEmpty2(prefix, s); } static String[] codeTokensAsStringArray(List tok) { int n = max(0, (l(tok) - 1) / 2); String[] out = new String[n]; for (int i = 0; i < n; i++) out[i] = tok.get(i * 2 + 1); return out; } static int jfind(String s, String in) { return jfind(javaTok(s), in); } static int jfind(List tok, String in) { return jfind(tok, 1, in); } static int jfind(List tok, int startIdx, String in) { return jfind(tok, startIdx, in, null); } static int jfind(List tok, String in, Object condition) { return jfind(tok, 1, in, condition); } static int jfind(List tok, String in, ITokCondition condition) { return jfind(tok, 1, in, condition); } static int jfind(List tok, int startIndex, String in, ITokCondition condition) { return jfind(tok, startIndex, in, toTokCondition(condition)); } static int jfind(List tok, int startIdx, String in, Object condition) { // LS tokin = jfind_preprocess(javaTok(in)); return jfind(tok, startIdx, javaTokForJFind_array(in), condition); } // assumes you preprocessed tokin static int jfind(List tok, List tokin) { return jfind(tok, 1, tokin); } static int jfind(List tok, int startIdx, List tokin) { return jfind(tok, startIdx, tokin, null); } static int jfind(List tok, int startIdx, String[] tokinC, Object condition) { return findCodeTokens(tok, startIdx, false, tokinC, condition); } static int jfind(List tok, int startIdx, List tokin, Object condition) { return jfind(tok, startIdx, codeTokensAsStringArray(tokin), condition); } static List jfind_preprocess(List tok) { for (String type : litlist("quoted", "id", "int")) replaceSublist(tok, ll("<", "", type, "", ">"), ll("<" + type + ">")); replaceSublist(tok, ll("\\", "", "*"), ll("\\*")); return tok; } static boolean checkTokCondition(Object condition, List tok, int i) { if (condition instanceof TokCondition) return ((TokCondition) condition).get(tok, i); return checkCondition(condition, tok, i); } static void replaceCollection(Collection dest, Collection src) { if (dest == src) return; dest.clear(); if (src != null) dest.addAll(src); } static void replaceListPart(List l, int i, int j, List l2) { replaceSublist(l, i, j, l2); } static String addPrefixIfNotEmpty2(String prefix, String s) { return empty(s) ? "" : addPrefix(prefix, s); } static TokCondition toTokCondition(ITokCondition condition) { return condition == null ? null : new TokCondition() { boolean get(List tok, int i) { return condition.get(tok, i); } }; } static boolean checkCondition(Object condition, Object... args) { return isTrue(callF(condition, args)); } static boolean checkCondition(IF1 condition, A arg) { return isTrue(callF(condition, arg)); } static abstract class VF1 implements IVF1 { public abstract void get(A a); } static class JSection extends SingleComponentPanel { JSection(Component c) { super(c); } String getTitle() { Border border = getBorder(); if (border instanceof TitledBorder) return ((TitledBorder) border).getTitle(); return null; } } static class Var implements IVar, ISetter { Var() { } Var(A v) { this.v = v; } // you can access this directly if you use one thread A v; public synchronized void set(A a) { if (v != a) { v = a; notifyAll(); } } public synchronized A get() { return v; } public synchronized boolean has() { return v != null; } public synchronized void clear() { v = null; } public String toString() { return str(this.get()); } } static class DefunctClassLoader { } static class Scorer { double score, total; // set to non-null if you want them filled List successes, errors; boolean verboseFailures, verboseAll; void addZeroToOne(double score) { ++total; this.score += clamp(score, 0, 1); } void addZeroToOneError(double error) { addZeroToOne(1 - error); } void addError() { add(false); } void addError(A info) { add(false, info); } void error(A info) { addError(info); } void addOK() { add(true); } void addOK(A info) { add(true, info); } void ok() { addOK(); } void ok(A info) { addOK(info); } boolean add(boolean correct) { ++total; if (correct) ++score; return correct; } boolean add(boolean correct, A info) { main.add(correct ? successes : errors, info); if (verboseAll || verboseFailures && !correct) _print((correct ? "[GOOD] " : "[BAD] ") + info); return add(correct); } // works if you use Scorer or Scorer void eq(Object a, Object b) { if (_eq(a, b)) add(true); else add(false, (A) (a + " != " + b)); } void print() { main.print(toString()); } public String toString() { return formatDouble(ratioToPercent(score, total), 1) + "% correct (n=" + formatDouble(total, 1) + ")"; } double get() { return ratioToPercent(score, total); } double percentScore() { return get(); } double score() { return get(); } boolean allCorrect() { return score == total; } void add(Scorer scorer) { if (scorer == null) return; total += scorer.total; score += scorer.score; addAll(successes, scorer.successes); addAll(errors, scorer.errors); } void collectErrors() { errors = new ArrayList(); } } static interface ITokCondition { // i = N Index boolean get(List tok, int i); } static abstract class TokCondition { // i = N Index abstract boolean get(List tok, int i); } static class SimpleLiveValue extends LiveValue { Class type; volatile A value; transient List onChange = synchroList(); SimpleLiveValue(Class type) { this.type = type; } SimpleLiveValue(Class type, A value) { this.value = value; this.type = type; } public Class getType() { return type; } public A get() { return value; } public void onChange(Runnable l) { onChange.add(l); } public void onChangeAndNow(Runnable l) { onChange(l); callF(l); } public void removeOnChangeListener(Runnable l) { onChange.remove(l); } void fireChanged() { pcallFAll(onChange); } void set(A a) { if (neq(value, a)) { value = a; fireChanged(); } } } static class ReliableSingleThread implements Runnable { boolean _isTransient() { return true; } // usually a Runnable. is allowed to call trigger() itself Object runnable; String name = "Single Thread"; // always cancel running thread and wait for it to end before starting new operation boolean cancelBeforeTrigger = false; // optional ownership marker, e.g. for DynModules F0 enter; int cancelTimeOut = 10000; boolean trigger = false; Thread thread; WeakReference threadBeingCancelled; ReliableSingleThread(Object runnable) { this.runnable = runnable; } void trigger() { go(); } synchronized void go() { if (cancelBeforeTrigger) cancel(); trigger = true; if (!running()) { AutoCloseable __1 = callF(enter); try { thread = startThread(name, new Runnable() { public void run() { try { AutoCloseable __2 = callF(enter); try { _run(); } finally { _close(__2); } } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "temp callF(enter);\r\n _run();"; } }); } finally { _close(__1); } } } public void run() { go(); } // so you can use the ! syntax void get() { go(); } synchronized boolean running() { return thread != null; } // use only if this is the last time you trigger this void triggerAndWait() { trigger(); waitUntilDone(); } void waitUntilDone() { while (running()) sleep(1); } void _run() { try { while (licensed()) { Thread oldThread; synchronized (this) { if (!trigger) { thread = null; break; } oldThread = getWeakRef(threadBeingCancelled); trigger = false; } if (oldThread != null && oldThread != currentThread()) oldThread.join(cancelTimeOut); pcallF(runnable); } } catch (Exception __e) { throw rethrow(__e); } } synchronized void cancel() { if (thread == null) return; threadBeingCancelled = new WeakReference(thread); cancelAndInterruptThread(thread); thread = null; } void cancelAndTrigger() { cancel(); trigger(); } synchronized boolean triggered() { return trigger; } void cleanMeUp() { cancel(); } ReliableSingleThread cancelBeforeTrigger() { cancelBeforeTrigger = true; return this; } } static class SingleComponentPanel extends JPanel { SingleComponentPanel() { super(new BorderLayout()); } SingleComponentPanel(Component component) { this(); if (component != null) setComponent(component); } void set(Component component) { setComponent(component); } void setComponent(Component component) { { swing(new Runnable() { public void run() { try { removeAll(); if (component != null) add(BorderLayout.CENTER, wrap(component)); _revalidate(SingleComponentPanel.this); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "removeAll();\r\n if (component != null)\r\n add(BorderLayout.CENTER, ..."; } }); } } // Sometimes we need this? void setComponentAndRevalidateParent(Component component) { setComponent(component); _revalidate(_getParent(this)); } void noComponent() { setComponent(null); } Component getComponent() { return getComponentCount() == 0 ? null : getComponent(0); } } // A concept should be an object, not just a string. // Functions that should always be there for child processes: static int concepts_internStringsLongerThan = 10; static ThreadLocal concepts_unlisted = new ThreadLocal(); // true = we can create instances of concepts with "new" without registering them automatically static boolean concepts_unlistedByDefault = false; static interface Derefable { Concept get(); } static interface IConceptIndex { // also for adding void update(Concept c); void remove(Concept c); } static interface IFieldIndex { Collection getAll(Val val); // returns a cloned list List allValues(); MultiSet allValues_multiSet(); } // Approach to persisting the Concepts object itself (in normal // DB operation, this is not done): For simplification, speed and // compactness, we make almost all the fields transient and store only // the concepts and the idCounter. To unstructure the Concepts object, // use unstructureConcepts() or postUnstructureConcepts(), then // re-set up any indices, listeners etc. // base class indicating nothing static class ConceptsChange { } // creation/change of a single concept static class ConceptChange extends ConceptsChange implements IFieldsToList { Concept c; ConceptChange() { } ConceptChange(Concept c) { this.c = c; } public String toString() { return shortClassName(this) + "(" + c + ")"; } public boolean equals(Object o) { if (!(o instanceof ConceptChange)) return false; ConceptChange __4 = (ConceptChange) o; return eq(c, __4.c); } public int hashCode() { int h = -1760609256; h = boostHashCombine(h, _hashCode(c)); return h; } public Object[] _fieldsToList() { return new Object[] { c }; } } // removal of a single concept // c.id is going to become 0 at some point, so we pass the // id separately static class ConceptDelete extends ConceptsChange implements IFieldsToList { static final String _fieldOrder = "id c"; long id; Concept c; ConceptDelete() { } ConceptDelete(long id, Concept c) { this.c = c; this.id = id; } public String toString() { return shortClassName(this) + "(" + id + ", " + c + ")"; } public boolean equals(Object o) { if (!(o instanceof ConceptDelete)) return false; ConceptDelete __5 = (ConceptDelete) o; return id == __5.id && eq(c, __5.c); } public int hashCode() { int h = -1734431213; h = boostHashCombine(h, _hashCode(id)); h = boostHashCombine(h, _hashCode(c)); return h; } public Object[] _fieldsToList() { return new Object[] { id, c }; } } // unknown change anywhere in concepts; consider it all dirty // (this one should not be used except for batch jobs) static class FullChange extends ConceptsChange implements IFieldsToList { FullChange() { } public String toString() { return shortClassName(this) + "(" + ")"; } public boolean equals(Object o) { return o instanceof FullChange; } public int hashCode() { int h = 733452095; return h; } public Object[] _fieldsToList() { return null; } } static class Concepts implements AutoCloseable { Map concepts = synchroTreeMap(); long idCounter; transient HashMap perClassData; // don't use directly, call miscMap... methods to access transient Map miscMap; // set to "-" for non-persistent (possibly not implemented) // also, can include a case ID ("#123/1") // TODO: have an actual directory instead transient String programID; // new mechanism transient Concepts parent; transient volatile long changes, changesWritten, lastChange; transient volatile java.util.Timer autoSaver; transient volatile boolean dontSave = false; transient volatile boolean savingConcepts, noXFullGrab; transient boolean vmBusSend = true; // set to false to avoid initial useless saving transient boolean initialSave = true; // 1 second + wait logic transient int autoSaveInterval = -1000; transient boolean useGZIP = true, quietSave; transient ReentrantLock lock = new ReentrantLock(true); transient ReentrantLock saverLock = new ReentrantLock(true); transient long lastSaveTook = -1, lastSaveWas, loadTook, uncompressedSize; transient float maxAutoSavePercentage = 10; transient List conceptIndices; transient Map, Map> fieldIndices; transient Map, Map> ciFieldIndices; // transient L saveActions = synchroList(); transient List preSave; transient Object classFinder = _defaultClassFinder(); // list of runnables transient List onAllChanged = synchroList(); transient Set onChange = new HashSet(); // VF1, to profile saving transient Object saveWrapper; // set _modified == created initially transient boolean modifyOnCreate = false; // set modified if back refs change transient boolean modifyOnBackRef = false; // instead of locking by bot transient boolean useFileLock = true; // OLD - not done anymore. transient bool collectForwardRefs transient FileBasedLock fileLock; // helps with schema evolution when concept subclasses disappear transient boolean storeBaseClassesInStructure = false; // assume backRefs are sane in order to speed up searches transient boolean useBackRefsForSearches = false; Concepts() { } Concepts(String programID) { this.programID = programID; } synchronized long internalID() { do { ++idCounter; } while (hasConcept(idCounter)); return idCounter; } synchronized HashMap perClassData() { if (perClassData == null) perClassData = new HashMap(); return perClassData; } void initProgramID() { if (programID == null) programID = getDBProgramID(); } // Now tries to load from bot first, then go to disk. Concepts load() { return load(false); } Concepts safeLoad() { return load(true); } Concepts load(boolean allDynamic) { initProgramID(); // try custom grabber Object dbGrabber = miscMapGet("dbGrabber"); if (dbGrabber != null && !isFalse(callF(dbGrabber))) return this; try { if (tryToGrab(allDynamic)) return this; } catch (Throwable e) { if (!exceptionMessageContains(e, "no xfullgrab")) printShortException(e); print("xfullgrab failed - loading DB of " + programID + " from disk"); } return loadFromDisk(allDynamic); } Concepts loadFromDisk() { return loadFromDisk(false); } Concepts loadFromDisk(boolean allDynamic) { if (nempty(concepts)) clearConcepts(); // DynamicObject_loading.set(true); // now done in unstructure() // try { // minimal crash recovery restoreLatestBackupIfConceptsFileEmpty(programID, "doIt", true); long time = now(); // empty map Map _concepts = concepts; readLocally2_allDynamic.set(allDynamic); AutoCloseable __3 = tempSetTL(readLocally2_classFinder, classFinder); try { readLocally2(this, programID, "concepts"); Map __concepts = concepts; concepts = _concepts; concepts.putAll(__concepts); int l = readLocally_stringLength; int tokrefs = unstructure_tokrefs; assignConceptsToUs(); loadTook = now() - time; done("Loaded " + n(l(concepts), "concepts"), time); try { if (fileSize(getProgramFile(programID, "idCounter.structure")) != 0) readLocally2(this, programID, "idCounter"); else calcIdCounter(); } catch (Throwable e) { _handleException(e); calcIdCounter(); } /*} finally { DynamicObject_loading.set(null); }*/ if (initialSave) allChanged(); return this; } finally { _close(__3); } } Concepts loadConcepts() { return load(); } boolean tryToGrab(boolean allDynamic) { if (sameSnippetID(programID, getDBProgramID())) return false; RemoteDB db = connectToDBOpt(programID); try { if (db != null) { loadGrab(db.fullgrab(), allDynamic); return true; } return false; } finally { _close(db); } } Concepts load(String grab) { return loadGrab(grab, false); } Concepts safeLoad(String grab) { return loadGrab(grab, true); } Concepts loadGrab(String grab, boolean allDynamic) { clearConcepts(); DynamicObject_loading.set(true); try { Map map = (Map) unstructure(grab, allDynamic, classFinder); concepts.putAll(map); assignConceptsToUs(); for (long l : map.keySet()) idCounter = max(idCounter, l); } finally { DynamicObject_loading.set(null); } allChanged(); return this; } void assignConceptsToUs() { // fix unstructure bugs for (Pair p : mapToPairs((Map) (Map) concepts)) if (!(p.b instanceof Concept)) { print("DROPPING non-existant concept " + p.a + ": " + dynShortName(p.b)); concepts.remove(p.a); } for (Concept c : values(concepts)) c._concepts = this; for (Concept c : values(concepts)) // doneLoading2 is called on all concepts after all concepts are loaded c._doneLoading2(); } String progID() { return programID == null ? getDBProgramID() : programID; } Concept getConcept(String id) { return empty(id) ? null : getConcept(parseLong(id)); } Concept getConcept(long id) { return (Concept) concepts.get((long) id); } Concept getConcept(RC ref) { return ref == null ? null : getConcept(ref.longID()); } boolean hasConcept(long id) { return concepts.containsKey((long) id); } void deleteConcept(long id) { Concept c = getConcept(id); if (c == null) print("Concept " + id + " not found"); else c.delete(); } void calcIdCounter() { long id_ = 0; for (long id : keys(concepts)) id_ = max(id_, id); idCounter = id_ + 1; saveLocally2(this, programID, "idCounter"); } File conceptsFile() { return getProgramFile(programID, useGZIP ? "concepts.structure.gz" : "concepts.structure"); } // used for locking when useFileLock is activated File lockFile() { return getProgramFile(programID, "concepts.lock"); } FileBasedLock fileLock() { if (fileLock == null) fileLock = new FileBasedLock(lockFile()); return fileLock; } void saveConceptsIfDirty() { saveConcepts(); } void save() { saveConcepts(); } void saveConcepts() { vmBus_send("saveConceptsCalled", Concepts.this); if (dontSave) return; initProgramID(); saverLock.lock(); savingConcepts = true; long start = now(), time; try { String s = null; // synchronized(main.class) { long _changes = changes; if (_changes == changesWritten) return; File f = conceptsFile(); lock.lock(); long fullTime = now(); try { saveLocally2(this, programID, "idCounter"); vmBus_send("idCounterWritten", Concepts.this, programID, "idCounter"); if (useGZIP) { vmBus_send("callingSaveWrapper", Concepts.this, saveWrapper); callRunnableWithWrapper(saveWrapper, new Runnable() { public void run() { try { vmBus_send("callingPreSave", Concepts.this, preSave); callFAll(preSave); vmBus_send("writingFile", Concepts.this, f); uncompressedSize = saveGZStructureToFile(f, cloneMap(concepts), makeStructureData()); vmBus_send("gzFileSaved", Concepts.this, f, uncompressedSize); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "vmBus_send callingPreSave(Concepts.this, preSave);\r\n callFAll(preS..."; } }); getProgramFile(programID, "concepts.structure").delete(); } else s = fullStructure(); } finally { lock.unlock(); } /*while (nempty(saveActions)) pcallF(popFirst(saveActions));*/ // only update when structure didn't fail changesWritten = _changes; if (!useGZIP) { time = now() - start; if (!quietSave) print("Saving " + toM(l(s)) + "M chars (" + /*+ changesWritten + ", "*/ time + " ms)"); start = now(); saveTextFile(f, javaTokWordWrap(s)); getProgramFile(programID, "concepts.structure.gz").delete(); } copyFile(f, getProgramFile(programID, "backups/concepts.structure" + (useGZIP ? ".gz" : "") + ".backup" + ymd() + "-" + formatInt(hours(), 2))); time = now() - start; if (!quietSave) print(programID + ": Saved " + toK(f.length()) + " K, " + n(concepts, "concepts") + " (" + time + " ms)"); lastSaveWas = fullTime; lastSaveTook = now() - fullTime; } finally { savingConcepts = false; saverLock.unlock(); } } void _autoSaveConcepts() { if (autoSaveInterval < 0 && maxAutoSavePercentage != 0) { long pivotTime = Math.round(lastSaveWas + lastSaveTook * 100.0 / maxAutoSavePercentage); if (now() < pivotTime) { // print("Skipping auto-save (last save took " + lastSaveTook + ")"); return; } } try { saveConcepts(); } catch (Throwable e) { print("Concept save failed, will try again: " + e); } } String fullStructure() { return structure(cloneMap(concepts), makeStructureData()); } structure_Data makeStructureData() { structure_Data data = new structure_Data(); if (storeBaseClassesInStructure) data.storeBaseClasses = true; return data; } void clearConcepts() { concepts.clear(); allChanged(); } void allChanged() { synchronized (this) { ++changes; lastChange = sysNow(); } if (vmBusSend) vmBus_send("conceptsChanged", this); pcallFAll(onAllChanged); } // auto-save every second if dirty synchronized void autoSaveConcepts() { if (autoSaver == null) { if (isTransient()) throw fail("Can't persist transient database"); autoSaver = doEvery_daemon(abs(autoSaveInterval), new Runnable() { public void run() { try { _autoSaveConcepts(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_autoSaveConcepts()"; } }); // print("Installed auto-saver (" + autoSaveInterval + " ms, " + progID() + ")"); } } public void close() { cleanMeUp(); } void cleanMeUp() { try { boolean shouldSave = autoSaver != null; if (autoSaver != null) { autoSaver.cancel(); autoSaver = null; } while (savingConcepts) sleepInCleanUp(10); if (shouldSave) saveConceptsIfDirty(); } catch (Throwable __e) { _handleException(__e); } { cleanUp(fileLock); fileLock = null; } } Map getIDsAndNames() { Map map = new HashMap(); Map cloned = cloneMap(concepts); for (long id : keys(cloned)) map.put(id, cloned.get(id).className); return map; } void deleteConcepts(List l) { ping(); if (l != null) for (Object o : cloneList(l)) if (o instanceof Long) { Concept c = concepts.get(o); if (c != null) c.delete(); } else if (o instanceof Concept) ((Concept) o).delete(); else warn("Can't delete " + getClassName(o)); } A conceptOfType(Class type) { IConceptCounter counter = conceptCounterForClass(type); if (counter != null) return (A) first(counter.allConcepts()); return firstOfType(allConcepts(), type); } List conceptsOfType(Class type) { List l = conceptsOfType_noParent(type); if (parent == null) return l; return concatLists_conservative(l, parent.conceptsOfType(type)); } List conceptsOfType_noParent(Class type) { ping(); IConceptCounter counter = conceptCounterForClass(type); if (counter != null) return (List) cloneList(counter.allConcepts()); return filterByType(allConcepts(), type); } List listConcepts(Class type) { return conceptsOfType(type); } List list(Class type) { return conceptsOfType(type); } List list_noParent(Class type) { return conceptsOfType_noParent(type); } // TODO: would be better to make this Cl (indices may return sets) List list(String type) { return conceptsOfType(type); } List conceptsOfType(String type) { return filterByDynamicType(allConcepts(), "main$" + type); } boolean hasConceptOfType(Class type) { return hasType(allConcepts(), type); } void persistConcepts() { loadConcepts(); autoSaveConcepts(); } // We love synonyms void conceptPersistence() { persistConcepts(); } Concepts persist() { persistConcepts(); return this; } void persist(Integer interval) { if (interval != null) autoSaveInterval = interval; persist(); } // Runs r if there is no concept of that type A ensureHas(Class c, Runnable r) { A a = conceptOfType(c); if (a == null) { r.run(); a = conceptOfType(c); if (a == null) throw fail("Concept not made by " + r + ": " + shortClassName(c)); } return a; } // Ensures that every concept of type c1 is ref'd by a concept of // type c2. // Type of func: voidfunc(concept) void ensureHas(Class c1, Class c2, Object func) { for (Concept a : conceptsOfType(c1)) { Concept b = findBackRef(a, c2); if (b == null) { callF(func, a); b = findBackRef(a, c2); if (b == null) throw fail("Concept not made by " + func + ": " + shortClassName(c2)); } } } // Type of func: voidfunc(concept) void forEvery(Class type, Object func) { for (Concept c : conceptsOfType(type)) callF(func, c); } int deleteAll(Class type) { List l = (List) conceptsOfType(type); for (Concept c : l) c.delete(); return l(l); } // always returns a new list (callers depend on this) Collection allConcepts() { synchronized (concepts) { return new ArrayList(values(concepts)); } } IConceptCounter conceptCounterForClass(Class c) { for (IFieldIndex idx : values(mapGet(fieldIndices, c))) if (idx instanceof IConceptCounter) return ((IConceptCounter) idx); for (IFieldIndex idx : values(mapGet(ciFieldIndices, c))) if (idx instanceof IConceptCounter) return ((IConceptCounter) idx); return null; } int countConcepts(Class c, Object... params) { int n = countConcepts_noParent(c, params); if (parent == null) return n; return n + parent.countConcepts(c, params); } int countConcepts_noParent(Class c, Object... params) { ping(); if (empty(params)) { IConceptCounter counter = conceptCounterForClass(c); if (counter != null) return counter.countConcepts(); return l(list_noParent(c)); } int n = 0; for (A x : list_noParent(c)) if (checkConceptFields(x, params)) ++n; return n; } int countConcepts(String c, Object... params) { ping(); if (empty(params)) return l(list(c)); int n = 0; for (Concept x : list(c)) if (checkConceptFields(x, params)) ++n; return n; } int countConcepts() { return l(concepts); } synchronized void addConceptIndex(IConceptIndex index) { if (conceptIndices == null) conceptIndices = new ArrayList(); conceptIndices.add(index); } synchronized void removeConceptIndex(IConceptIndex index) { if (conceptIndices == null) return; conceptIndices.remove(index); if (empty(conceptIndices)) conceptIndices = null; } synchronized void addFieldIndex(Class c, String field, IFieldIndex index) { if (fieldIndices == null) fieldIndices = new HashMap(); Map map = fieldIndices.get(c); if (map == null) fieldIndices.put(c, map = new HashMap()); map.put(field, index); } synchronized IFieldIndex getFieldIndex(Class c, String field) { if (fieldIndices == null) return null; Map map = fieldIndices.get(c); return map == null ? null : map.get(field); } synchronized void addCIFieldIndex(Class c, String field, IFieldIndex index) { if (ciFieldIndices == null) ciFieldIndices = new HashMap(); Map map = ciFieldIndices.get(c); if (map == null) ciFieldIndices.put(c, map = new HashMap()); map.put(field, index); } synchronized IFieldIndex getCIFieldIndex(Class c, String field) { if (ciFieldIndices == null) return null; Map map = ciFieldIndices.get(c); return map == null ? null : map.get(field); } // inter-process methods RC xnew(String name, Object... values) { return new RC(cnew(name, values)); } void xset(long id, String field, Object value) { xset(new RC(id), field, value); } void xset(RC c, String field, Object value) { if (value instanceof RC) value = getConcept((RC) value); cset(getConcept(c), field, value); } Object xget(long id, String field) { return xget(new RC(id), field); } Object xget(RC c, String field) { return xgetPost(cget(getConcept(c), field)); } Object xgetPost(Object o) { o = deref(o); if (o instanceof Concept) return new RC((Concept) o); return o; } void xdelete(long id) { xdelete(new RC(id)); } void xdelete(RC c) { getConcept(c).delete(); } void xdelete(List l) { for (RC c : l) xdelete(c); } List xlist() { return map("toPassRef", allConcepts()); } List xlist(String className) { return map("toPassRef", conceptsOfType(className)); } boolean isTransient() { return eq(programID, "-"); } String xfullgrab() { if (noXFullGrab) throw fail("no xfullgrab (DB too large)"); Lock __1 = lock(); lock(__1); try { if (changes == changesWritten && !isTransient()) return loadConceptsStructure(programID); return fullStructure(); } finally { unlock(__1); } } /* dev. Either xfullgrabGZipped() { lock lock(); if (changes == changesWritten && !isTransient()) ret loadConceptsStructure(programID); ret fullStructure(); }*/ void xshutdown() { // Killing whole VM if someone wants this DB to shut down cleanKillVM(); } long xchangeCount() { return changes; } int xcount() { return countConcepts(); } void register(Concept c) { ping(); if (c._concepts == this) return; if (c._concepts != null) throw fail("Can't re-register"); c.id = internalID(); c.created = now(); if (modifyOnCreate) c._setModified(c.created); register_phase2(c); } // also called by replaceConceptAndUpdateRefs void register_phase2(Concept c) { c._concepts = this; concepts.put((long) c.id, c); for (Concept.Ref r : c._refs()) r.index(); c.change(); } void registerKeepingID(Concept c) { if (c._concepts == this) return; if (c._concepts != null) throw fail("Can't re-register"); c._concepts = this; concepts.put((long) c.id, c); c.change(); } void conceptChanged(Concept c) { fireChange(new ConceptChange(c)); allChanged(); if (conceptIndices != null) for (IConceptIndex index : conceptIndices) index.update(c); } boolean hasUnsavedData() { return changes != changesWritten || savingConcepts; } synchronized Object miscMapGet(Object key) { return mapGet(miscMap, key); } synchronized Object miscMapPut(Object key, Object value) { if (miscMap == null) miscMap = new HashMap(); return miscMap.put(key, value); } synchronized void miscMapRemove(Object key) { mapRemove(miscMap, key); } // Note: auto-typing can fool you, make sure create returns // a wide enough type synchronized A miscMapGetOrCreate(Object key, IF0 create) { if (containsKey(miscMap, key)) return (A) miscMap.get(key); A value = create.get(); miscMapPut(key, value); return value; } void setParent(Concepts parent) { this.parent = parent; } void fireChange(ConceptsChange change) { pcallFAll(onChange, change); } void onChange(IVF1 l) { addChangeListener(l); } void addChangeListener(IVF1 l) { syncAdd(onChange, l); } void removeChangeListener(IVF1 l) { syncRemove(onChange, l); } void addPreSave(Runnable r) { preSave = syncAddOrCreate(preSave, r); } } // end of Concepts static class Concept extends DynamicObject { // Where we belong transient Concepts _concepts; long id; long created, _modified; List refs; List backRefs; // used only internally (cnew) Concept(String className) { super(className); _created(); } Concept() { if (!_loading()) { // className = shortClassName(this); // XXX - necessary? // print("New concept of type " + className); _created(); } } Concept(boolean unlisted) { if (!unlisted) _created(); } public String toString() { return shortDynamicClassName(this) + " " + id; } static boolean loading() { return _loading(); } static boolean _loading() { return dynamicObjectIsLoading(); } void _created() { if (!concepts_unlistedByDefault && !eq(concepts_unlisted.get(), true)) db_mainConcepts().register(this); } class Ref implements Derefable, IF0 { A value; Ref() { if (!dynamicObjectIsLoading()) registerRef(); } void registerRef() { vmBus_send("registeringConceptRef", this); } Ref(A value) { this.value = value; registerRef(); index(); } // get owning concept (source) Concept concept() { return Concept.this; } // get target public A get() { return value; } boolean has() { return value != null; } boolean set(A a) { if (a == value) return false; unindex(); value = a; index(); return true; } void set(Ref ref) { set(ref.get()); } void clear() { set((A) null); } boolean validRef() { return value != null && _concepts != null && _concepts == value._concepts; } // TODO: sync all the indexing and unindexing!? void index() { if (validRef()) { value._addBackRef(this); change(); } } Ref unindex() { if (validRef()) { value._removeBackRef(this); change(); } return this; } void unindexAndDrop() { unindex(); _removeRef(this); } void change() { Concept.this.change(); } public String toString() { return str(value); } } class RefL extends AbstractList { List> l = new ArrayList(); RefL() { } RefL(List l) { replaceWithList(l); } public void clear() { while (!isEmpty()) removeLast(this); } public void replaceWithList(List l) { clear(); for (A a : unnull(l)) add(a); } public A set(int i, A o) { Ref ref = syncGet(l, i); A prev = ref.get(); ref.set(o); return prev; } public void add(int i, A o) { syncAdd(l, i, new Ref(o)); } public A get(int i) { return syncGet(l, i).get(); } public A remove(int i) { return syncRemove(l, i).get(); } public int size() { return syncL(l); } public boolean contains(Object o) { if (o instanceof Concept) for (Ref r : l) if (eq(r.get(), o)) return true; return super.contains(o); } } void delete() { // name = "[defunct " + name + "]"; // defunct = true; // energy = 0; // clean refs for (Ref r : unnull(refs)) r.unindex(); refs = null; // set back refs to null for (Ref r : cloneList(backRefs)) r.set((Concept) null); backRefs = null; if (_concepts != null) { _concepts.concepts.remove(id); _concepts.fireChange(new ConceptDelete(id, this)); _concepts.allChanged(); if (_concepts.conceptIndices != null) for (IConceptIndex index : _concepts.conceptIndices) index.remove(this); _concepts = null; } id = 0; } BaseXRef export() { return new BaseXRef(_concepts.progID(), id); } // notice system of a change in this object void change() { _setModified(now()); _change_withoutUpdatingModifiedField(); } void _setModified(long modified) { _modified = modified; } void _change_withoutUpdatingModifiedField() { if (_concepts != null) _concepts.conceptChanged(this); } void _change() { change(); } String _programID() { return _concepts == null ? getDBProgramID() : _concepts.progID(); } // overridable void _addBackRef(Concept.Ref ref) { backRefs = addDyn_quickSync(backRefs, ref); _backRefsModified(); } void _backRefsModified() { if (_concepts != null && _concepts.modifyOnBackRef) change(); } void _removeBackRef(Concept.Ref ref) { backRefs = removeDyn_quickSync(backRefs, ref); _backRefsModified(); } void _removeRef(Concept.Ref ref) { refs = removeDyn_quickSync(refs, ref); } int _backRefCount() { return syncL(backRefs); } // convenience methods void _setField(String field, Object value) { cset(this, field, value); } void _setFields(Object... values) { cset(this, values); } Concepts concepts() { return _concepts; } boolean isDeleted() { return id == 0; } void _doneLoading2() { Map map = _fieldMigrations(); if (map != null) for (Map.Entry __0 : _entrySet(map)) { String oldField = __0.getKey(); FieldMigration m = __0.getValue(); crenameField_noOverwrite(this, oldField, m.newField); } } static class FieldMigration implements IFieldsToList { String newField; FieldMigration() { } FieldMigration(String newField) { this.newField = newField; } public String toString() { return shortClassName(this) + "(" + newField + ")"; } public boolean equals(Object o) { if (!(o instanceof FieldMigration)) return false; FieldMigration __6 = (FieldMigration) o; return eq(newField, __6.newField); } public int hashCode() { int h = 558692372; h = boostHashCombine(h, _hashCode(newField)); return h; } public Object[] _fieldsToList() { return new Object[] { newField }; } } // value is Map _fieldMigrations() { return null; } // new wrapper to get a copy of the refs list // so we can eventually drop the refs field Collection _refs() { return scanConceptForRefs(this); } // for debugging List _rawRefsField() { return refs; } Concepts _concepts() { return _concepts; } } // end of Concept // remote reference (for inter-process communication or // external databases). Formerly "PassRef". // prepared for string ids if we do them later static class RC { transient Object owner; String id; // make serialisation happy RC() { } RC(long id) { this.id = str(id); } RC(Object owner, long id) { this.id = str(id); this.owner = owner; } RC(Concept c) { this(c.id); } long longID() { return parseLong(id); } public String toString() { return id; } transient RemoteDB db; String getString(String field) { return db.xS(this, field); } Object get(String field) { return db.xget(this, field); } void set(String field, Object value) { db.xset(this, field, value); } } // Reference to a concept in another program static class BaseXRef { String programID; long id; BaseXRef() { } BaseXRef(String programID, long id) { this.id = id; this.programID = programID; } public boolean equals(Object o) { if (!(o instanceof BaseXRef)) return false; BaseXRef r = (BaseXRef) o; return eq(programID, r.programID) && eq(id, r.id); } public int hashCode() { return programID.hashCode() + (int) id; } } // BaseXRef as a concept static class XRef extends Concept { BaseXRef ref; XRef() { } XRef(BaseXRef ref) { this.ref = ref; _doneLoading2(); } // after we have been added to concepts void _doneLoading2() { getIndex().put(ref, this); } HashMap getIndex() { return getXRefIndex(_concepts); } } static synchronized HashMap getXRefIndex(Concepts concepts) { HashMap cache = (HashMap) concepts.perClassData().get(XRef.class); if (cache == null) concepts.perClassData.put(XRef.class, cache = new HashMap()); return cache; } // uses mainConcepts static XRef lookupOrCreateXRef(BaseXRef ref) { XRef xref = getXRefIndex(db_mainConcepts()).get(ref); if (xref == null) xref = new XRef(ref); return xref; } // define standard concept functions to use main concepts // Now in db_mainConcepts() /*static void cleanMeUp_concepts() { if (db_mainConcepts() != null) db_mainConcepts().cleanMeUp(); // mainConcepts = null; // TODO }*/ static void loadAndAutoSaveConcepts() { db_mainConcepts().persist(); } static void loadAndAutoSaveConcepts(int interval) { db_mainConcepts().persist(interval); } static RC toPassRef(Concept c) { return new RC(c); } // so we can instantiate the program to run as a bare DB bot static void concepts_setUnlistedByDefault(boolean b) { concepts_unlistedByDefault = b; } final static class Rect { int x, y, w, h; Rect() { } Rect(Rectangle r) { x = r.x; y = r.y; w = r.width; h = r.height; } Rect(int x, int y, int w, int h) { this.h = h; this.w = w; this.y = y; this.x = x; } Rect(Pt p, int w, int h) { this.h = h; this.w = w; x = p.x; y = p.y; } Rect(Rect r) { x = r.x; y = r.y; w = r.w; h = r.h; } Rectangle getRectangle() { return new Rectangle(x, y, w, h); } public boolean equals(Object o) { return stdEq2(this, o); } public int hashCode() { return stdHash2(this); } public String toString() { return x + "," + y + " / " + w + "," + h; } int x1() { return x; } int y1() { return y; } int x2() { return x + w; } int y2() { return y + h; } boolean contains(Pt p) { return contains(p.x, p.y); } boolean contains(int _x, int _y) { return _x >= x && _y >= y && _x < x + w && _y < y + h; } boolean empty() { return w <= 0 || h <= 0; } } static class Pt implements Comparable { int x, y; Pt() { } Pt(Point p) { x = p.x; y = p.y; } Pt(int x, int y) { this.y = y; this.x = x; } Point getPoint() { return new Point(x, y); } public boolean equals(Object o) { return o instanceof Pt && x == ((Pt) o).x && y == ((Pt) o).y; } public int hashCode() { return boostHashCombine(x, y); } // compare in scan order public int compareTo(Pt p) { if (y != p.y) return cmp(y, p.y); return cmp(x, p.x); } public String toString() { return x + ", " + y; } } static class ProgramScan { static int threads = isWindows() ? 500 : 10; // hmm... static int timeout = 5000; static String ip = "127.0.0.1"; // This range is not used anymore anyway static int quickScanFrom = 10000, quickScanTo = 10999; // Android will always only have one if we don't screw up static int maxNumberOfVMs_android = 4; // 100; static int maxNumberOfVMs_nonAndroid = 50; static int maxNumberOfVMs; static boolean verbose = false; static class Program { int port; String helloString; Program(int port, String helloString) { this.helloString = helloString; this.port = port; } } static List scan() { try { return scan(1, 65535); } catch (Exception __e) { throw rethrow(__e); } } static List scan(int fromPort, int toPort) { return scan(fromPort, toPort, new int[0]); } static List scan(int fromPort, int toPort, int[] preferredPorts) { try { Set preferredPortsSet = new HashSet(asList(preferredPorts)); int scanSize = toPort - fromPort + 1; String name = toPort < 10000 ? "bot" : "program"; int threads = isWindows() ? min(500, scanSize) : min(scanSize, 10); final ExecutorService es = Executors.newFixedThreadPool(threads); if (verbose) print(firstToUpper(name) + "-scanning " + ip + " with timeout " + timeout + " ms in " + threads + " threads."); startTiming(); List> futures = new ArrayList(); List ports = new ArrayList(); for (int port : preferredPorts) { futures.add(checkPort(es, ip, port, timeout)); ports.add(port); } for (int port = fromPort; port <= toPort; port++) if (!preferredPortsSet.contains(port) && !forbiddenPort(port)) { futures.add(checkPort(es, ip, port, timeout)); ports.add(port); } es.shutdown(); List programs = new ArrayList(); long time = now(); int i = 0; for (final Future f : futures) { if (verbose) print("Waiting for port " + get(ports, i++) + " at time " + (now() - time)); Program p = f.get(); if (p != null) programs.add(p); } // stopTiming("Port Scan " + scanSize + ", " + n(threads, "threads") + ": ", 250); if (verbose) print("Found " + programs.size() + " " + name + "(s) on " + ip); return programs; } catch (Exception __e) { throw rethrow(__e); } } static Future checkPort(final ExecutorService es, final String ip, final int port, final int timeout) { return es.submit(new Callable() { @Override public Program call() { try { Socket socket = new Socket(); try { socket.setSoTimeout(timeout); socket.connect(new InetSocketAddress(ip, port), timeout); // if (verbose) print("Connected to " + ip + ":" + port); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8")); String hello = or(in.readLine(), "?"); return new Program(port, hello); } finally { socket.close(); } } catch (Exception ex) { return null; } } }); } static List quickScan() { return scan(quickScanFrom, quickScanTo); } static List quickBotScan() { return quickBotScan(new int[0]); } static List quickBotScan(int[] preferredPorts) { if (maxNumberOfVMs == 0) maxNumberOfVMs = isAndroid() ? maxNumberOfVMs_android : maxNumberOfVMs_nonAndroid; return scan(4999, 5000 + maxNumberOfVMs - 1, preferredPorts); } } static interface ISetter { void set(A a); } static abstract class F0 { abstract A get(); } static abstract class F1 { abstract B get(A a); } // you still need to implement hasNext() and next() static abstract class IterableIterator implements Iterator, Iterable { public Iterator iterator() { return this; } public void remove() { unsupportedOperation(); } } abstract static class RandomAccessAbstractList extends AbstractList implements RandomAccess { } /** * this class is fully thread-safe */ static class Flag implements Runnable { private boolean up = false; /** * returns true if flag was down before (i.e. flag was actually raised right now) */ public synchronized boolean raise() { if (!up) { up = true; notifyAll(); return true; } else return false; } public synchronized void waitUntilUp() { while (!up) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void waitUntilUp(long timeout) { if (!up) { try { wait(timeout); } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized boolean isUp() { return up; } boolean get() { return isUp(); } public String toString() { return isUp() ? "up" : "down"; } // currently does a semi-active wait with latency = 50 ms public void waitForThisOr(Flag otherFlag) { try { while (!isUp() && !otherFlag.isUp()) Thread.sleep(50); } catch (Exception __e) { throw rethrow(__e); } } public void run() { raise(); } } static interface IF0 { A get(); } static abstract class CloseableIterableIterator extends IterableIterator implements AutoCloseable { public void close() throws Exception { } } static interface IFieldsToList { Object[] _fieldsToList(); } static interface IF2 { C get(A a, B b); } static interface Producer { // null when end public A next(); } static interface IF1 { B get(A a); } static interface IVF1 { void get(A a); } static interface IVar extends IF0 { void set(A a); A get(); default boolean has() { return get() != null; } default void clear() { set(null); } } static class SynchronizedList extends SynchronizedCollection implements List { SynchronizedList() { } /*final*/ List list; SynchronizedList(List list) { super(list); this.list = list; } SynchronizedList(List list, Object mutex) { super(list, mutex); this.list = list; } public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) { return list.equals(o); } } public int hashCode() { synchronized (mutex) { return list.hashCode(); } } public E get(int index) { synchronized (mutex) { return list.get(index); } } public E set(int index, E element) { synchronized (mutex) { return list.set(index, element); } } public void add(int index, E element) { synchronized (mutex) { list.add(index, element); } } public E remove(int index) { synchronized (mutex) { return list.remove(index); } } public int indexOf(Object o) { synchronized (mutex) { return list.indexOf(o); } } public int lastIndexOf(Object o) { synchronized (mutex) { return list.lastIndexOf(o); } } public boolean addAll(int index, Collection c) { synchronized (mutex) { return list.addAll(index, c); } } public ListIterator listIterator() { // Must be manually synched by user return list.listIterator(); } public ListIterator listIterator(int index) { // Must be manually synched by user return list.listIterator(index); } public List subList(int fromIndex, int toIndex) { synchronized (mutex) { return new SynchronizedList<>(list.subList(fromIndex, toIndex), mutex); } } @Override public void replaceAll(java.util.function.UnaryOperator operator) { synchronized (mutex) { list.replaceAll(operator); } } @Override public void sort(Comparator c) { synchronized (mutex) { list.sort(c); } } /** * SynchronizedRandomAccessList instances are serialized as * SynchronizedList instances to allow them to be deserialized * in pre-1.4 JREs (which do not have SynchronizedRandomAccessList). * This method inverts the transformation. As a beneficial * side-effect, it also grafts the RandomAccess marker onto * SynchronizedList instances that were serialized in pre-1.4 JREs. * * Note: Unfortunately, SynchronizedRandomAccessList instances * serialized in 1.4.1 and deserialized in 1.4 will become * SynchronizedList instances, as this method was missing in 1.4. */ @java.io.Serial private Object readResolve() { return (list instanceof RandomAccess ? new SynchronizedRandomAccessList<>(list) : this); } } // immutable, has strong refs final static class _MethodCache { final Class c; final HashMap> cache = new HashMap(); _MethodCache(Class c) { this.c = c; _init(); } void _init() { Class _c = c; while (_c != null) { for (Method m : _c.getDeclaredMethods()) if (!isAbstract(m) && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); _c = _c.getSuperclass(); } // add default methods - this might lead to a duplication // because the overridden method is also added, but it's not // a problem except for minimal performance loss. for (Class intf : allInterfacesImplementedBy(c)) for (Method m : intf.getDeclaredMethods()) if (m.isDefault() && !reflection_isForbiddenMethod(m)) multiMapPut(cache, m.getName(), makeAccessible(m)); } // Returns only matching methods Method findMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } Method findStaticMethod(String method, Object[] args) { try { List m = cache.get(method); if (m == null) return null; int n = m.size(); for (int i = 0; i < n; i++) { Method me = m.get(i); if (isStaticMethod(me) && call_checkArgs(me, args, false)) return me; } return null; } catch (Exception __e) { throw rethrow(__e); } } } static class LineBuffer { VF1 onLine; StringBuilder currentLine = new StringBuilder(); LineBuffer() { } LineBuffer(VF1 onLine) { this.onLine = onLine; } void append(String s) { append(s, onLine); } void append(String s, VF1 onLine) { currentLine.append(s); if (contains(s, '\n')) { int i = 0, j; s = str(currentLine); while ((j = indexOf(s, i, '\n')) >= 0) { String line = dropTrailingBackslashR(substring(s, i, j)); callF(onLine, line); i = j + 1; } currentLine = new StringBuilder(substring(s, i)); } } int size() { return l(currentLine); } } static class Matches { String[] m; Matches() { } Matches(String... m) { this.m = m; } String get(int i) { return i < m.length ? m[i] : null; } String unq(int i) { return unquote(get(i)); } String tlc(int i) { return unq(i).toLowerCase(); } boolean bool(int i) { return "true".equals(unq(i)); } // for matchStart String rest() { return m[m.length - 1]; } int psi(int i) { return Integer.parseInt(unq(i)); } public String toString() { return "Matches(" + joinWithComma(quoteAll(asList(m))) + ")"; } public int hashCode() { return _hashCode(toList(m)); } public boolean equals(Object o) { return o instanceof Matches && arraysEqual(m, ((Matches) o).m); } } static abstract class LiveValue { abstract Class getType(); abstract A get(); abstract void onChange(Runnable l); abstract void removeOnChangeListener(Runnable l); void onChangeAndNow(Runnable l) { onChange(l); callF(l); } } static class BlockDiff { public CopyBlock asCopyBlock() { return null; } public NewBlock asNewBlock() { return null; } } static class CopyBlock extends BlockDiff { int firstLine, lines; CopyBlock(int firstLine, int lines) { this.firstLine = firstLine; this.lines = lines; } public CopyBlock asCopyBlock() { return this; } public int getFirstLine() { return firstLine; } public int getLines() { return lines; } } static class NewBlock extends BlockDiff { int originalStart; List contents; NewBlock(int originalStart, List contents) { this.originalStart = originalStart; this.contents = contents; } public NewBlock asNewBlock() { return this; } public int getOriginalStart() { return originalStart; } public List getContents() { return contents; } } static class ExplodedLine { int type; String left, right; int leftIndex, rightIndex; ExplodedLine(int type, String left, String right, int leftIndex, int rightIndex) { this.type = type; this.left = left; this.right = right; this.leftIndex = leftIndex; this.rightIndex = rightIndex; } public int getType() { return type; } public String getLeft() { return left; } public String getRight() { return right; } public int getLeftIndex() { return leftIndex; } public int getRightIndex() { return rightIndex; } } static class BlockDiffer { public static final int IDENTICAL = 0; public static final int DIFFERENT = 1; public static final int LEFT_ONLY = 2; public static final int RIGHT_ONLY = 3; private static void printChange(EGDiff.change change) { if (change != null) { System.out.println("line0=" + change.line0 + ", line1=" + change.line1 + ", inserted=" + change.inserted + ", deleted=" + change.deleted); printChange(change.link); } } /** * Generates the text content of a Unified-format context diff between 2 files * (NB the 'files-changed' header must be added separately). */ public static List generateUniDiff(List fileA, List fileB, int contextSize) { EGDiff diff = new EGDiff(fileA.toArray(), fileB.toArray()); EGDiff.change change = diff.diff_2(false); if (change != null) { int inserted, deleted; List hunkLines = new ArrayList(); int cumulExtraLinesBwrtA = 0; // Each hunk is generated with a header do { int line0 = change.line0, line1 = change.line1; int changeStart = ((line1 < line0) ? line1 : line0); int contextStart = ((changeStart > contextSize) ? changeStart - contextSize : 0); int headerPosn = hunkLines.size(); // Provide the first lines of context for (int i = contextStart; i < changeStart; i++) // System.out.println(" " + fileA.get(i)); hunkLines.add(" " + fileA.get(i)); boolean hunkFinish = false; // Step through each change giving the change lines and following context do { inserted = change.inserted; deleted = change.deleted; line0 = change.line0; line1 = change.line1; if (// An insert comes earlier line1 < line0) while (inserted-- > 0) hunkLines.add("+" + fileB.get(line1++)); while (deleted-- > 0) hunkLines.add("-" + fileA.get(line0++)); while (inserted-- > 0) hunkLines.add("+" + fileB.get(line1++)); // Lines following are trailing context, identical in fileA and fileB // The next change may overlap the context, so check and if so, form one hunk EGDiff.change nextChange = change.link; int nextChangeStart = fileA.size(); if (nextChange != null) nextChangeStart = ((nextChange.line1 < nextChange.line0) ? nextChange.line1 : nextChange.line0); if (nextChangeStart - line0 > contextSize * 2) { // A separate hunk nextChangeStart = line0 + contextSize; hunkFinish = true; } if (nextChangeStart > fileA.size()) // Limit to file size nextChangeStart = fileA.size(); while (line0 < nextChangeStart) { hunkLines.add(" " + fileA.get(line0++)); // Keep in sync with trailing context line1++; } change = change.link; } while (!hunkFinish && change != null); int hunkStartB = contextStart + cumulExtraLinesBwrtA; int hunkTotA = line0 - contextStart; int hunkTotB = line1 - hunkStartB; hunkLines.add(headerPosn, "@@ -" + (contextStart + 1) + ',' + hunkTotA + " +" + (hunkStartB + 1) + ',' + hunkTotB + " @@"); cumulExtraLinesBwrtA += hunkTotB - hunkTotA; } while (change != null); return hunkLines; } return null; } /* For testing: private static void printUniDiff(List fileA, List fileB, int contextSize) { List uniDiff = generateUniDiff(fileA, fileB, contextSize); if (uniDiff != null) for (int j = 0; j < uniDiff.size(); j++) System.out.println(uniDiff.get(j)); } */ public static List diffLines(List lines, List reference) { List diffs = new ArrayList(); EGDiff diff = new EGDiff(reference.toArray(), lines.toArray()); EGDiff.change change = diff.diff_2(false); // printChange(change); // printUniDiff(reference, lines, 3); int l0 = 0, l1 = 0; while (change != null) { if (change.line0 > l0 && change.line1 > l1) diffs.add(new CopyBlock(l0, change.line0 - l0)); if (change.inserted != 0) diffs.add(new NewBlock(change.line1, lines.subList(change.line1, change.line1 + change.inserted))); l0 = change.line0 + change.deleted; l1 = change.line1 + change.inserted; change = change.link; } if (l0 < reference.size()) diffs.add(new CopyBlock(l0, reference.size() - l0)); return diffs; } /** * fills files with empty lines to align matching blocks * * @param file1 first file * @param file2 second file * @return an array with two lists */ public static List explode(List file1, List file2) { List lines = new ArrayList(); List diffs = BlockDiffer.diffLines(file2, file1); int lastLineCopied = 0, rightOnlyStart = -1, rightPosition = 0; for (int i = 0; i < diffs.size(); i++) { BlockDiff diff = diffs.get(i); if (diff instanceof CopyBlock) { CopyBlock copyBlock = (CopyBlock) diff; if (lastLineCopied < copyBlock.getFirstLine()) { if (rightOnlyStart >= 0) { int overlap = Math.min(lines.size() - rightOnlyStart, copyBlock.getFirstLine() - lastLineCopied); // lines.subList(rightOnlyStart, rightOnlyStart+overlap).clear(); convertRightOnlyToDifferent(lines, rightOnlyStart, overlap, file1, lastLineCopied); lastLineCopied += overlap; } addBlock(lines, LEFT_ONLY, file1, lastLineCopied, copyBlock.getFirstLine(), lastLineCopied, -1); } addBlock(lines, IDENTICAL, file1, copyBlock.getFirstLine(), copyBlock.getFirstLine() + copyBlock.getLines(), copyBlock.getFirstLine(), rightPosition); rightPosition += copyBlock.getLines(); lastLineCopied = copyBlock.getFirstLine() + copyBlock.getLines(); rightOnlyStart = -1; } else if (diff instanceof NewBlock) { NewBlock newBlock = (NewBlock) diff; /*if (nextDiff instanceof BlockDiffer.CopyBlock) { BlockDiffer.CopyBlock copyBlock = (BlockDiffer.CopyBlock) nextDiff; copyBlock.getFirstLine()-lastLineCopied*/ rightOnlyStart = lines.size(); addBlock(lines, RIGHT_ONLY, newBlock.getContents(), 0, newBlock.getContents().size(), -1, rightPosition); rightPosition += newBlock.getContents().size(); } } if (rightOnlyStart >= 0) { int overlap = Math.min(lines.size() - rightOnlyStart, file1.size() - lastLineCopied); // lines.subList(rightOnlyStart, rightOnlyStart+overlap).clear(); convertRightOnlyToDifferent(lines, rightOnlyStart, overlap, file1, lastLineCopied); lastLineCopied += overlap; } addBlock(lines, LEFT_ONLY, file1, lastLineCopied, file1.size(), lastLineCopied, -1); return lines; } private static void convertRightOnlyToDifferent(List lines, int start, int numLines, List leftLines, int leftStart) { for (int i = 0; i < numLines; i++) { ExplodedLine line = lines.get(start + i); lines.set(start + i, new ExplodedLine(DIFFERENT, leftLines.get(i + leftStart), line.getRight(), i + leftStart, line.getRightIndex())); } } private static void addBlock(List lines, int type, List srcLines, int start, int end, int leftStart, int rightStart) { for (int i = start; i < end; i++) lines.add(new ExplodedLine(type, type == RIGHT_ONLY ? "" : srcLines.get(i), type == LEFT_ONLY ? "" : srcLines.get(i), type == RIGHT_ONLY ? -1 : i - start + leftStart, type == LEFT_ONLY ? -1 : i - start + rightStart)); } public static List condense(List lines) { List result = new ArrayList(); for (Iterator i = lines.iterator(); i.hasNext(); ) { ExplodedLine line = i.next(); if (line.getType() == IDENTICAL) { if (result.isEmpty() || result.get(result.size() - 1).getType() != IDENTICAL) result.add(new ExplodedLine(IDENTICAL, "[...]", "[...]", -1, -1)); } else result.add(line); } return result; } } static class Q implements AutoCloseable { String name = "Unnamed Queue"; List q = synchroLinkedList(); ReliableSingleThread rst = new ReliableSingleThread(new Runnable() { public void run() { try { _run(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "_run()"; } }); volatile boolean retired = false; Q() { } Q(String name) { this.name = name; } void add(Runnable r) { q.add(r); _trigger(); } void addInFront(Runnable r) { q.add(0, r); _trigger(); } void _trigger() { rst.name = name; rst.go(); } void add(Object r) { add(toRunnable(r)); } void _run() { Runnable r; while (licensed() && !retired && (r = syncPopFirst(q)) != null) { try { r.run(); } catch (Throwable __e) { _handleException(__e); } } } // TODO: interrupt thread public void close() { retired = true; } // legacy function void done() { } boolean isEmpty() { return q.isEmpty(); } int size() { return q.size(); } // clients can synchronize on this Object mutex() { return q; } List snapshot() { return cloneList(q); } } static class SynchronizedMap implements Map, Serializable { SynchronizedMap() { } /*final*/ // Backing Map Map m; /*final*/ // Object on which to synchronize Object mutex; SynchronizedMap(Map m) { this.m = Objects.requireNonNull(m); mutex = this; } SynchronizedMap(Map m, Object mutex) { this.m = m; this.mutex = mutex; } public int size() { synchronized (mutex) { return m.size(); } } public boolean isEmpty() { synchronized (mutex) { return m.isEmpty(); } } public boolean containsKey(Object key) { synchronized (mutex) { return m.containsKey(key); } } public boolean containsValue(Object value) { synchronized (mutex) { return m.containsValue(value); } } public V get(Object key) { synchronized (mutex) { return m.get(key); } } public V put(K key, V value) { synchronized (mutex) { return m.put(key, value); } } public V remove(Object key) { synchronized (mutex) { return m.remove(key); } } public void putAll(Map map) { synchronized (mutex) { m.putAll(map); } } public void clear() { synchronized (mutex) { m.clear(); } } private transient Set keySet; private transient Set> entrySet; private transient Collection values; public Set keySet() { synchronized (mutex) { if (keySet == null) keySet = new SynchronizedSet<>(m.keySet(), mutex); return keySet; } } public Set> entrySet() { synchronized (mutex) { if (entrySet == null) entrySet = new SynchronizedSet<>(m.entrySet(), mutex); return entrySet; } } public Collection values() { synchronized (mutex) { if (values == null) values = new SynchronizedCollection<>(m.values(), mutex); return values; } } public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) { return m.equals(o); } } public int hashCode() { synchronized (mutex) { return m.hashCode(); } } public String toString() { synchronized (mutex) { return m.toString(); } } // Override default methods in Map @Override public V getOrDefault(Object k, V defaultValue) { synchronized (mutex) { return m.getOrDefault(k, defaultValue); } } @Override public void forEach(BiConsumer action) { synchronized (mutex) { m.forEach(action); } } @Override public void replaceAll(BiFunction function) { synchronized (mutex) { m.replaceAll(function); } } @Override public V putIfAbsent(K key, V value) { synchronized (mutex) { return m.putIfAbsent(key, value); } } @Override public boolean remove(Object key, Object value) { synchronized (mutex) { return m.remove(key, value); } } @Override public boolean replace(K key, V oldValue, V newValue) { synchronized (mutex) { return m.replace(key, oldValue, newValue); } } @Override public V replace(K key, V value) { synchronized (mutex) { return m.replace(key, value); } } @Override public V computeIfAbsent(K key, java.util.function.Function mappingFunction) { synchronized (mutex) { return m.computeIfAbsent(key, mappingFunction); } } @Override public V computeIfPresent(K key, BiFunction remappingFunction) { synchronized (mutex) { return m.computeIfPresent(key, remappingFunction); } } @Override public V compute(K key, BiFunction remappingFunction) { synchronized (mutex) { return m.compute(key, remappingFunction); } } @Override public V merge(K key, V value, BiFunction remappingFunction) { synchronized (mutex) { return m.merge(key, value, remappingFunction); } } @java.io.Serial private void writeObject(ObjectOutputStream s) throws IOException { synchronized (mutex) { s.defaultWriteObject(); } } } static interface IResourceLoader { String loadSnippet(String snippetID); // with libs String getTranspiled(String snippetID); int getSnippetType(String snippetID); String getSnippetTitle(String snippetID); File loadLibrary(String snippetID); default File pathToJavaXJar() { return pathToJavaxJar_noResourceLoader(); } // may return null, then caller compiles themselves default File getSnippetJar(String snippetID, String transpiledSrc) { return null; } } static class Either { byte which; Object value; Either() { } Either(int which, Object value) { this.which = (byte) which; this.value = value; } boolean isA() { return which == 1; } boolean isB() { return which == 2; } A a() { if (which != 1) _failMe(); return (A) value; } B b() { if (which != 2) _failMe(); return (B) value; } A aOpt() { return which != 1 ? null : (A) value; } B bOpt() { return which != 2 ? null : (B) value; } void _failMe() { throw fail("Either object is of wrong type: " + shortClassName(value)); } public String toString() { return "Either" + (isA() ? "A" : "B") + "(" + value + ")"; } } static class JLineHeightTextArea extends JTextArea { double lineHeightFactor = 1.0; JLineHeightTextArea() { } JLineHeightTextArea(double lineHeightFactor) { this.lineHeightFactor = lineHeightFactor; } @Override public FontMetrics getFontMetrics(Font font) { return new FontMetricsWrapper(super.getFontMetrics(font)) { @Override public int getHeight() { return iround(super.getHeight() * lineHeightFactor); } }; } } static class proxy_InvocationHandler implements InvocationHandler { Object target; proxy_InvocationHandler() { } proxy_InvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) { return call(target, method.getName(), unnull(args)); } } static class Pair implements Comparable> { A a; B b; Pair() { } Pair(A a, B b) { this.b = b; this.a = a; } public int hashCode() { return hashCodeFor(a) + 2 * hashCodeFor(b); } public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof Pair)) return false; Pair t = (Pair) o; return eq(a, t.a) && eq(b, t.b); } public String toString() { return "<" + a + ", " + b + ">"; } public int compareTo(Pair p) { if (p == null) return 1; int i = ((Comparable) a).compareTo(p.a); if (i != 0) return i; return ((Comparable) b).compareTo(p.b); } } static interface IResourceHolder { A add(A a); } static interface Swingable { JComponent visualize(); } static abstract class DialogIO implements AutoCloseable { String line; boolean eos, loud, noClose; Lock lock = lock(); abstract String readLineImpl(); abstract boolean isStillConnected(); abstract void sendLine(String line); abstract boolean isLocalConnection(); abstract Socket getSocket(); int getPort() { Socket s = getSocket(); return s == null ? 0 : s.getPort(); } boolean helloRead = false; int shortenOutputTo = 500; String readLineNoBlock() { String l = line; line = null; return l; } boolean waitForLine() { try { ping(); if (line != null) return true; // print("Readline"); line = readLineImpl(); // print("Readline done: " + line); if (line == null) eos = true; return line != null; } catch (Exception __e) { throw rethrow(__e); } } String readLine() { waitForLine(); helloRead = true; return readLineNoBlock(); } String ask(String s, Object... args) { if (loud) return askLoudly(s, args); if (!helloRead) readLine(); if (args.length != 0) s = format3(s, args); sendLine(s); return readLine(); } String askLoudly(String s, Object... args) { if (!helloRead) readLine(); if (args.length != 0) s = format3(s, args); print("> " + shorten(s, shortenOutputTo)); sendLine(s); String answer = readLine(); print("< " + shorten(answer, shortenOutputTo)); return answer; } void pushback(String l) { if (line != null) throw fail(); line = l; helloRead = false; } } static abstract class DialogHandler { abstract void run(DialogIO io); } static class BetterLabel extends JLabel { boolean autoToolTip = true; BetterLabel() { // Listeners given out to componentPopupMenu must not directly // reference the outer object (-> weak map problem). final WeakReference me = new WeakReference<>(this); componentPopupMenu(this, BetterLabel_menuItems(me)); } BetterLabel(String text) { this(); this.setText(text); } public void setText(String text) { super.setText(text); if (autoToolTip) if (// HTML labels make super-huge, confusing tool tips !swic(text, "")) setToolTipText(nullIfEmpty(text)); } } // moved outside of class for GC reasons (see above) static VF1 BetterLabel_menuItems(final WeakReference me) { return new VF1() { public void get(JPopupMenu menu) { try { addMenuItem(menu, "Copy text to clipboard", new Runnable() { public void run() { try { copyTextToClipboard(me.get().getText()); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "copyTextToClipboard(me.get().getText());"; } }); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "addMenuItem(menu, \"Copy text to clipboard\", r {\r\n copyTextToClipboard(me..."; } }; } // elements are put to front when added (not when accessed) static class MRUCache extends LinkedHashMap { int maxSize = 10; MRUCache() { } MRUCache(int maxSize) { this.maxSize = maxSize; } protected boolean removeEldestEntry(Map.Entry eldest) { return size() > maxSize; } Object _serialize() { return ll(maxSize, cloneLinkedHashMap(this)); } static MRUCache _deserialize(List l) { MRUCache m = new MRUCache(); m.maxSize = (int) first(l); m.putAll((LinkedHashMap) second(l)); return m; } } static ThreadLocal DynamicObject_loading = new ThreadLocal(); static class DynamicObject { // just the name, without the "main$" String className; // string key = dynamic field // interface key = dynamic interface // dropped the type parameters 2021/5/19 to allow for dynamic interfaces LinkedHashMap /**/ fieldValues; DynamicObject() { } // className = just the name, without the "main$" DynamicObject(String className) { this.className = className; } Map _map() { return fieldValues; } public String toString() { return getClass() == DynamicObject.class ? "dyn " + className : super.toString(); } } static class PersistableThrowable { String className; String msg; String stacktrace; PersistableThrowable() { } PersistableThrowable(Throwable e) { if (e == null) className = "Crazy Null Error"; else { className = getClassName(e).replace('/', '.'); msg = e.getMessage(); stacktrace = getStackTrace_noRecord(e); } } public String toString() { return nempty(msg) ? className + ": " + msg : className; } } static class SynchronizedSortedMap extends SynchronizedMap implements SortedMap { private final SortedMap sm; SynchronizedSortedMap(SortedMap m) { super(m); sm = m; } SynchronizedSortedMap(SortedMap m, Object mutex) { super(m, mutex); sm = m; } public Comparator comparator() { synchronized (mutex) { return sm.comparator(); } } public SortedMap subMap(K fromKey, K toKey) { synchronized (mutex) { return new SynchronizedSortedMap<>(sm.subMap(fromKey, toKey), mutex); } } public SortedMap headMap(K toKey) { synchronized (mutex) { return new SynchronizedSortedMap<>(sm.headMap(toKey), mutex); } } public SortedMap tailMap(K fromKey) { synchronized (mutex) { return new SynchronizedSortedMap<>(sm.tailMap(fromKey), mutex); } } public K firstKey() { synchronized (mutex) { return sm.firstKey(); } } public K lastKey() { synchronized (mutex) { return sm.lastKey(); } } } /** * A class to compare vectors of objects. The result of comparison * is a list of change objects which form an * edit script. The objects compared are traditionally lines * of text from two files. Comparison options such as "ignore * whitespace" are implemented by modifying the equals * and hashcode methods for the objects compared. *

* The basic algorithm is described in:
* "An O(ND) Difference Algorithm and its Variations", Eugene Myers, * Algorithmica Vol. 1 No. 2, 1986, p 251. *

* This class outputs different results from GNU diff 1.15 on some * inputs. Our results are actually better (smaller change list, smaller * total size of changes), but it would be nice to know why. Perhaps * there is a memory overwrite bug in GNU diff 1.15. * * @author Stuart D. Gathman, translated from GNU diff 1.15 * Copyright (C) 2000 Business Management Systems, Inc. *

* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. *

* You should have received a copy of the * GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ static class EGDiff { /** * Prepare to find differences between two arrays. Each element of * the arrays is translated to an "equivalence number" based on * the result of equals. The original Object arrays * are no longer needed for computing the differences. They will * be needed again later to print the results of the comparison as * an edit script, if desired. */ public EGDiff(Object[] a, Object[] b) { Hashtable h = new Hashtable(a.length + b.length); filevec[0] = new file_data(a, h); filevec[1] = new file_data(b, h); } /** * 1 more than the maximum equivalence value used for this or its * sibling file. */ private int equiv_max = 1; /** * When set to true, the comparison uses a heuristic to speed it up. * With this heuristic, for files with a constant small density * of changes, the algorithm is linear in the file size. */ public boolean heuristic = false; /** * When set to true, the algorithm returns a guarranteed minimal * set of changes. This makes things slower, sometimes much slower. */ public boolean no_discards = false; private int[] xvec, yvec; /* Vectors being compared. */ private int[] fdiag; /* Vector, indexed by diagonal, containing the X coordinate of the point furthest along the given diagonal in the forward search of the edit matrix. */ private int[] bdiag; /* Vector, indexed by diagonal, containing the X coordinate of the point furthest along the given diagonal in the backward search of the edit matrix. */ private int fdiagoff, bdiagoff; private final file_data[] filevec = new file_data[2]; private int cost; /** * Find the midpoint of the shortest edit script for a specified * portion of the two files. *

* We scan from the beginnings of the files, and simultaneously from the ends, * doing a breadth-first search through the space of edit-sequence. * When the two searches meet, we have found the midpoint of the shortest * edit sequence. *

* The value returned is the number of the diagonal on which the midpoint lies. * The diagonal number equals the number of inserted lines minus the number * of deleted lines (counting only lines before the midpoint). * The edit cost is stored into COST; this is the total number of * lines inserted or deleted (counting only lines before the midpoint). *

* This function assumes that the first lines of the specified portions * of the two files do not match, and likewise that the last lines do not * match. The caller must trim matching lines from the beginning and end * of the portions it is going to specify. *

* Note that if we return the "wrong" diagonal value, or if * the value of bdiag at that diagonal is "wrong", * the worst this can do is cause suboptimal diff output. * It cannot cause incorrect diff output. */ private int diag(int xoff, int xlim, int yoff, int ylim) { // Give the compiler a chance. final int[] fd = fdiag; // Additional help for the compiler. final int[] bd = bdiag; // Still more help for the compiler. final int[] xv = xvec; // And more and more . . . final int[] yv = yvec; // Minimum valid diagonal. final int dmin = xoff - ylim; // Maximum valid diagonal. final int dmax = xlim - yoff; // Center diagonal of top-down search. final int fmid = xoff - yoff; // Center diagonal of bottom-up search. final int bmid = xlim - ylim; // Limits of top-down search. int fmin = fmid, fmax = fmid; // Limits of bottom-up search. int bmin = bmid, bmax = bmid; /* True if southeast corner is on an odd diagonal with respect to the northwest. */ final boolean odd = (fmid - bmid & 1) != 0; fd[fdiagoff + fmid] = xoff; bd[bdiagoff + bmid] = xlim; for (int c = 1; ; ++c) { int d; /* Active diagonal. */ boolean big_snake = false; /* Extend the top-down search by an edit step in each diagonal. */ if (fmin > dmin) fd[fdiagoff + --fmin - 1] = -1; else ++fmin; if (fmax < dmax) fd[fdiagoff + ++fmax + 1] = -1; else --fmax; for (d = fmax; d >= fmin; d -= 2) { int x, y, oldx, tlo = fd[fdiagoff + d - 1], thi = fd[fdiagoff + d + 1]; if (tlo >= thi) x = tlo + 1; else x = thi; oldx = x; y = x - d; while (x < xlim && y < ylim && xv[x] == yv[y]) { ++x; ++y; } if (x - oldx > 20) big_snake = true; fd[fdiagoff + d] = x; if (odd && bmin <= d && d <= bmax && bd[bdiagoff + d] <= fd[fdiagoff + d]) { cost = 2 * c - 1; return d; } } /* Similar extend the bottom-up search. */ if (bmin > dmin) bd[bdiagoff + --bmin - 1] = Integer.MAX_VALUE; else ++bmin; if (bmax < dmax) bd[bdiagoff + ++bmax + 1] = Integer.MAX_VALUE; else --bmax; for (d = bmax; d >= bmin; d -= 2) { int x, y, oldx, tlo = bd[bdiagoff + d - 1], thi = bd[bdiagoff + d + 1]; if (tlo < thi) x = tlo; else x = thi - 1; oldx = x; y = x - d; while (x > xoff && y > yoff && xv[x - 1] == yv[y - 1]) { --x; --y; } if (oldx - x > 20) big_snake = true; bd[bdiagoff + d] = x; if (!odd && fmin <= d && d <= fmax && bd[bdiagoff + d] <= fd[fdiagoff + d]) { cost = 2 * c; return d; } } /* Heuristic: check occasionally for a diagonal that has made lots of progress compared with the edit distance. If we have any such, find the one that has made the most progress and return it as if it had succeeded. With this heuristic, for files with a constant small density of changes, the algorithm is linear in the file size. */ if (c > 200 && big_snake && heuristic) { int best = 0; int bestpos = -1; for (d = fmax; d >= fmin; d -= 2) { int dd = d - fmid; if ((fd[fdiagoff + d] - xoff) * 2 - dd > 12 * (c + (dd > 0 ? dd : -dd))) { if (fd[fdiagoff + d] * 2 - dd > best && fd[fdiagoff + d] - xoff > 20 && fd[fdiagoff + d] - d - yoff > 20) { int k; int x = fd[fdiagoff + d]; /* We have a good enough best diagonal; now insist that it end with a significant snake. */ for (k = 1; k <= 20; k++) if (xvec[x - k] != yvec[x - d - k]) break; if (k == 21) { best = fd[fdiagoff + d] * 2 - dd; bestpos = d; } } } } if (best > 0) { cost = 2 * c - 1; return bestpos; } best = 0; for (d = bmax; d >= bmin; d -= 2) { int dd = d - bmid; if ((xlim - bd[bdiagoff + d]) * 2 + dd > 12 * (c + (dd > 0 ? dd : -dd))) { if ((xlim - bd[bdiagoff + d]) * 2 + dd > best && xlim - bd[bdiagoff + d] > 20 && ylim - (bd[bdiagoff + d] - d) > 20) { /* We have a good enough best diagonal; now insist that it end with a significant snake. */ int k; int x = bd[bdiagoff + d]; for (k = 0; k < 20; k++) if (xvec[x + k] != yvec[x - d + k]) break; if (k == 20) { best = (xlim - bd[bdiagoff + d]) * 2 + dd; bestpos = d; } } } } if (best > 0) { cost = 2 * c - 1; return bestpos; } } } } /** * Compare in detail contiguous subsequences of the two files * which are known, as a whole, to match each other. *

* The results are recorded in the vectors filevec[N].changed_flag, by * storing a 1 in the element for each line that is an insertion or deletion. *

* The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1. *

* Note that XLIM, YLIM are exclusive bounds. * All line numbers are origin-0 and discarded lines are not counted. */ private void compareseq(int xoff, int xlim, int yoff, int ylim) { /* Slide down the bottom initial diagonal. */ while (xoff < xlim && yoff < ylim && xvec[xoff] == yvec[yoff]) { ++xoff; ++yoff; } /* Slide up the top initial diagonal. */ while (xlim > xoff && ylim > yoff && xvec[xlim - 1] == yvec[ylim - 1]) { --xlim; --ylim; } /* Handle simple cases. */ if (xoff == xlim) while (yoff < ylim) filevec[1].changed_flag[1 + filevec[1].realindexes[yoff++]] = true; else if (yoff == ylim) while (xoff < xlim) filevec[0].changed_flag[1 + filevec[0].realindexes[xoff++]] = true; else { /* Find a point of correspondence in the middle of the files. */ int d = diag(xoff, xlim, yoff, ylim); int c = cost; int b = bdiag[bdiagoff + d]; if (c == 1) { /* This should be impossible, because it implies that one of the two subsequences is empty, and that case was handled above without calling `diag'. Let's verify that this is true. */ throw new IllegalArgumentException("Empty subsequence"); } else { /* Use that point to split this problem into two subproblems. */ compareseq(xoff, b, yoff, b - d); /* This used to use f instead of b, but that is incorrect! It is not necessarily the case that diagonal d has a snake from b to f. */ compareseq(b, xlim, b - d, ylim); } } } /** * Discard lines from one file that have no matches in the other file. */ private void discard_confusing_lines() { filevec[0].discard_confusing_lines(filevec[1]); filevec[1].discard_confusing_lines(filevec[0]); } private boolean inhibit = false; /** * Adjust inserts/deletes of blank lines to join changes * as much as possible. */ private void shift_boundaries() { if (inhibit) return; filevec[0].shift_boundaries(filevec[1]); filevec[1].shift_boundaries(filevec[0]); } public interface ScriptBuilder { /** * Scan the tables of which lines are inserted and deleted, * producing an edit script. * * @param changed0 true for lines in first file which do not match 2nd * @param len0 number of lines in first file * @param changed1 true for lines in 2nd file which do not match 1st * @param len1 number of lines in 2nd file * @return a linked list of changes - or null */ public change build_script(boolean[] changed0, int len0, boolean[] changed1, int len1); } /** * Scan the tables of which lines are inserted and deleted, * producing an edit script in reverse order. */ static class ReverseScript implements ScriptBuilder { public change build_script(final boolean[] changed0, int len0, final boolean[] changed1, int len1) { change script = null; int i0 = 0, i1 = 0; while (i0 < len0 || i1 < len1) { if (changed0[1 + i0] || changed1[1 + i1]) { int line0 = i0, line1 = i1; /* Find # lines changed here in each file. */ while (changed0[1 + i0]) ++i0; while (changed1[1 + i1]) ++i1; /* Record this change. */ script = new change(line0, line1, i0 - line0, i1 - line1, script); } /* We have reached lines in the two files that match each other. */ i0++; i1++; } return script; } } static class ForwardScript implements ScriptBuilder { /** * Scan the tables of which lines are inserted and deleted, * producing an edit script in forward order. */ public change build_script(final boolean[] changed0, int len0, final boolean[] changed1, int len1) { change script = null; int i0 = len0, i1 = len1; while (i0 >= 0 || i1 >= 0) { if (changed0[i0] || changed1[i1]) { int line0 = i0, line1 = i1; /* Find # lines changed here in each file. */ while (changed0[i0]) --i0; while (changed1[i1]) --i1; /* Record this change. */ script = new change(i0, i1, line0 - i0, line1 - i1, script); } /* We have reached lines in the two files that match each other. */ i0--; i1--; } return script; } } /** * Standard ScriptBuilders. */ public final static ScriptBuilder forwardScript = new ForwardScript(), reverseScript = new ReverseScript(); /* Report the differences of two files. DEPTH is the current directory depth. */ public final change diff_2(final boolean reverse) { return diff(reverse ? reverseScript : forwardScript); } /** * Get the results of comparison as an edit script. The script * is described by a list of changes. The standard ScriptBuilder * implementations provide for forward and reverse edit scripts. * Alternate implementations could, for instance, list common elements * instead of differences. * * @param bld an object to build the script from change flags * @return the head of a list of changes */ public change diff(final ScriptBuilder bld) { /* Some lines are obviously insertions or deletions because they don't match anything. Detect them now, and avoid even thinking about them in the main comparison algorithm. */ discard_confusing_lines(); /* Now do the main comparison algorithm, considering just the undiscarded lines. */ xvec = filevec[0].undiscarded; yvec = filevec[1].undiscarded; int diags = filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines + 3; fdiag = new int[diags]; fdiagoff = filevec[1].nondiscarded_lines + 1; bdiag = new int[diags]; bdiagoff = filevec[1].nondiscarded_lines + 1; compareseq(0, filevec[0].nondiscarded_lines, 0, filevec[1].nondiscarded_lines); fdiag = null; bdiag = null; /* Modify the results slightly to make them prettier in cases where that can validly be done. */ shift_boundaries(); /* Get the results of comparison in the form of a chain of `struct change's -- an edit script. */ return bld.build_script(filevec[0].changed_flag, filevec[0].buffered_lines, filevec[1].changed_flag, filevec[1].buffered_lines); } /** * The result of comparison is an "edit script": a chain of change objects. * Each change represents one place where some lines are deleted * and some are inserted. *

* LINE0 and LINE1 are the first affected lines in the two files (origin 0). * DELETED is the number of lines deleted here from file 0. * INSERTED is the number of lines inserted here in file 1. *

* If DELETED is 0 then LINE0 is the number of the line before * which the insertion was done; vice versa for INSERTED and LINE1. */ public static class change { /** * Previous or next edit command. */ public change link; /** * # lines of file 1 changed here. */ public final int inserted; /** * # lines of file 0 changed here. */ public final int deleted; /** * Line number of 1st deleted line. */ public final int line0; /** * Line number of 1st inserted line. */ public final int line1; /** * Cons an additional entry onto the front of an edit script OLD. * LINE0 and LINE1 are the first affected lines in the two files (origin 0). * DELETED is the number of lines deleted here from file 0. * INSERTED is the number of lines inserted here in file 1. *

* If DELETED is 0 then LINE0 is the number of the line before * which the insertion was done; vice versa for INSERTED and LINE1. */ public change(int line0, int line1, int deleted, int inserted, change old) { this.line0 = line0; this.line1 = line1; this.inserted = inserted; this.deleted = deleted; this.link = old; // System.err.println(line0+","+line1+","+inserted+","+deleted); } } /** * Data on one input file being compared. */ class file_data { /** * Allocate changed array for the results of comparison. */ void clear() { /* Allocate a flag for each line of each file, saying whether that line is an insertion or deletion. Allocate an extra element, always zero, at each end of each vector. */ changed_flag = new boolean[buffered_lines + 2]; } /** * Return equiv_count[I] as the number of lines in this file * that fall in equivalence class I. * * @return the array of equivalence class counts. */ int[] equivCount() { int[] equiv_count = new int[equiv_max]; for (int i = 0; i < buffered_lines; ++i) ++equiv_count[equivs[i]]; return equiv_count; } /** * Discard lines that have no matches in another file. *

* A line which is discarded will not be considered by the actual * comparison algorithm; it will be as if that line were not in the file. * The file's `realindexes' table maps virtual line numbers * (which don't count the discarded lines) into real line numbers; * this is how the actual comparison algorithm produces results * that are comprehensible when the discarded lines are counted. *

* When we discard a line, we also mark it as a deletion or insertion * so that it will be printed in the output. * * @param f the other file */ void discard_confusing_lines(file_data f) { clear(); /* Set up table of which lines are going to be discarded. */ final byte[] discarded = discardable(f.equivCount()); /* Don't really discard the provisional lines except when they occur in a run of discardables, with nonprovisionals at the beginning and end. */ filterDiscards(discarded); /* Actually discard the lines. */ discard(discarded); } /** * Mark to be discarded each line that matches no line of another file. * If a line matches many lines, mark it as provisionally discardable. * * @param counts The count of each equivalence number for the other file. * @return 0=nondiscardable, 1=discardable or 2=provisionally discardable * for each line */ private byte[] discardable(final int[] counts) { final int end = buffered_lines; final byte[] discards = new byte[end]; final int[] equivs = this.equivs; int many = 5; int tem = end / 64; /* Multiply MANY by approximate square root of number of lines. That is the threshold for provisionally discardable lines. */ while ((tem = tem >> 2) > 0) many *= 2; for (int i = 0; i < end; i++) { int nmatch; if (equivs[i] == 0) continue; nmatch = counts[equivs[i]]; if (nmatch == 0) discards[i] = 1; else if (nmatch > many) discards[i] = 2; } return discards; } /** * Don't really discard the provisional lines except when they occur * in a run of discardables, with nonprovisionals at the beginning * and end. */ private void filterDiscards(final byte[] discards) { final int end = buffered_lines; for (int i = 0; i < end; i++) { /* Cancel provisional discards not in middle of run of discards. */ if (discards[i] == 2) discards[i] = 0; else if (discards[i] != 0) { /* We have found a nonprovisional discard. */ int j; int length; int provisional = 0; /* Find end of this run of discardable lines. Count how many are provisionally discardable. */ for (j = i; j < end; j++) { if (discards[j] == 0) break; if (discards[j] == 2) ++provisional; } /* Cancel provisional discards at end, and shrink the run. */ while (j > i && discards[j - 1] == 2) { discards[--j] = 0; --provisional; } /* Now we have the length of a run of discardable lines whose first and last are not provisional. */ length = j - i; /* If 1/4 of the lines in the run are provisional, cancel discarding of all provisional lines in the run. */ if (provisional * 4 > length) { while (j > i) if (discards[--j] == 2) discards[j] = 0; } else { int consec; int minimum = 1; int tem = length / 4; /* MINIMUM is approximate square root of LENGTH/4. A subrun of two or more provisionals can stand when LENGTH is at least 16. A subrun of 4 or more can stand when LENGTH >= 64. */ while ((tem = tem >> 2) > 0) minimum *= 2; minimum++; /* Cancel any subrun of MINIMUM or more provisionals within the larger run. */ for (j = 0, consec = 0; j < length; j++) if (discards[i + j] != 2) consec = 0; else if (minimum == ++consec) /* Back up to start of subrun, to cancel it all. */ j -= consec; else if (minimum < consec) discards[i + j] = 0; /* Scan from beginning of run until we find 3 or more nonprovisionals in a row or until the first nonprovisional at least 8 lines in. Until that point, cancel any provisionals. */ for (j = 0, consec = 0; j < length; j++) { if (j >= 8 && discards[i + j] == 1) break; if (discards[i + j] == 2) { consec = 0; discards[i + j] = 0; } else if (discards[i + j] == 0) consec = 0; else consec++; if (consec == 3) break; } /* I advances to the last line of the run. */ i += length - 1; /* Same thing, from end. */ for (j = 0, consec = 0; j < length; j++) { if (j >= 8 && discards[i - j] == 1) break; if (discards[i - j] == 2) { consec = 0; discards[i - j] = 0; } else if (discards[i - j] == 0) consec = 0; else consec++; if (consec == 3) break; } } } } } /** * Actually discard the lines. * * @param discards flags lines to be discarded */ private void discard(final byte[] discards) { final int end = buffered_lines; int j = 0; for (int i = 0; i < end; ++i) if (no_discards || discards[i] == 0) { undiscarded[j] = equivs[i]; realindexes[j++] = i; } else changed_flag[1 + i] = true; nondiscarded_lines = j; } file_data(Object[] data, Hashtable h) { buffered_lines = data.length; equivs = new int[buffered_lines]; undiscarded = new int[buffered_lines]; realindexes = new int[buffered_lines]; for (int i = 0; i < data.length; ++i) { Integer ir = (Integer) h.get(data[i]); if (ir == null) h.put(data[i], new Integer(equivs[i] = equiv_max++)); else equivs[i] = ir.intValue(); } } /** * Adjust inserts/deletes of blank lines to join changes * as much as possible. *

* We do something when a run of changed lines include a blank * line at one end and have an excluded blank line at the other. * We are free to choose which blank line is included. * `compareseq' always chooses the one at the beginning, * but usually it is cleaner to consider the following blank line * to be the "change". The only exception is if the preceding blank line * would join this change to other changes. * * @param f the file being compared against */ void shift_boundaries(file_data f) { final boolean[] changed = changed_flag; final boolean[] other_changed = f.changed_flag; int i = 0; int j = 0; int i_end = buffered_lines; int preceding = -1; int other_preceding = -1; for (; ; ) { int start, end, other_start; /* Scan forwards to find beginning of another run of changes. Also keep track of the corresponding point in the other file. */ while (i < i_end && !changed[1 + i]) { while (other_changed[1 + j++]) /* Non-corresponding lines in the other file will count as the preceding batch of changes. */ other_preceding = j; i++; } if (i == i_end) break; start = i; other_start = j; for (; ; ) { /* Now find the end of this run of changes. */ while (i < i_end && changed[1 + i]) i++; end = i; /* If the first changed line matches the following unchanged one, and this run does not follow right after a previous run, and there are no lines deleted from the other file here, then classify the first changed line as unchanged and the following line as changed in its place. */ /* You might ask, how could this run follow right after another? Only because the previous run was shifted here. */ if (end != i_end && equivs[start] == equivs[end] && !other_changed[1 + j] && end != i_end && !((preceding >= 0 && start == preceding) || (other_preceding >= 0 && other_start == other_preceding))) { changed[1 + end] = true; changed[1 + start++] = false; ++i; /* Since one line-that-matches is now before this run instead of after, we must advance in the other file to keep in synch. */ ++j; } else break; } preceding = i; other_preceding = j; } } /** * Number of elements (lines) in this file. */ final int buffered_lines; /** * Vector, indexed by line number, containing an equivalence code for * each line. It is this vector that is actually compared with that * of another file to generate differences. */ private final int[] equivs; /** * Vector, like the previous one except that * the elements for discarded lines have been squeezed out. */ final int[] undiscarded; /** * Vector mapping virtual line numbers (not counting discarded lines) * to real ones (counting those lines). Both are origin-0. */ final int[] realindexes; /** * Total number of nondiscarded lines. */ int nondiscarded_lines; /** * Array, indexed by real origin-1 line number, * containing true for a line that is an insertion or a deletion. * The results of comparison are stored here. */ boolean[] changed_flag; } } static class SynchronizedRandomAccessList extends SynchronizedList implements RandomAccess { SynchronizedRandomAccessList() { } SynchronizedRandomAccessList(List list) { super(list); } SynchronizedRandomAccessList(List list, Object mutex) { super(list, mutex); } public List subList(int fromIndex, int toIndex) { synchronized (mutex) { return new SynchronizedRandomAccessList<>(list.subList(fromIndex, toIndex), mutex); } } @java.io.Serial private static final long serialVersionUID = 1530674583602358482L; /** * Allows instances to be deserialized in pre-1.4 JREs (which do * not have SynchronizedRandomAccessList). SynchronizedList has * a readResolve method that inverts this transformation upon * deserialization. */ @java.io.Serial private Object writeReplace() { return new SynchronizedList<>(list); } } static class SynchronizedSet extends SynchronizedCollection implements Set { SynchronizedSet() { } SynchronizedSet(Set s) { super(s); } SynchronizedSet(Set s, Object mutex) { super(s, mutex); } public boolean equals(Object o) { if (this == o) return true; synchronized (mutex) { return c.equals(o); } } public int hashCode() { synchronized (mutex) { return c.hashCode(); } } } static class SynchronizedCollection implements Collection, Serializable { SynchronizedCollection() { } @java.io.Serial private static final long serialVersionUID = 3053995032091335093L; // Conditionally serializable @SuppressWarnings("serial") Collection /*final*/ c; // Conditionally serializable @SuppressWarnings("serial") Object /*final*/ mutex; SynchronizedCollection(Collection c) { this.c = Objects.requireNonNull(c); mutex = this; } SynchronizedCollection(Collection c, Object mutex) { this.c = Objects.requireNonNull(c); this.mutex = Objects.requireNonNull(mutex); } public int size() { synchronized (mutex) { return c.size(); } } public boolean isEmpty() { synchronized (mutex) { return c.isEmpty(); } } public boolean contains(Object o) { synchronized (mutex) { return c.contains(o); } } public Object[] toArray() { synchronized (mutex) { return c.toArray(); } } public T[] toArray(T[] a) { synchronized (mutex) { return c.toArray(a); } } public T[] toArray(java.util.function.IntFunction f) { synchronized (mutex) { return c.toArray(f); } } public Iterator iterator() { // Must be manually synched by user! return c.iterator(); } public boolean add(E e) { synchronized (mutex) { return c.add(e); } } public boolean remove(Object o) { synchronized (mutex) { return c.remove(o); } } public boolean containsAll(Collection coll) { synchronized (mutex) { return c.containsAll(coll); } } public boolean addAll(Collection coll) { synchronized (mutex) { return c.addAll(coll); } } public boolean removeAll(Collection coll) { synchronized (mutex) { return c.removeAll(coll); } } public boolean retainAll(Collection coll) { synchronized (mutex) { return c.retainAll(coll); } } public void clear() { synchronized (mutex) { c.clear(); } } public String toString() { synchronized (mutex) { return c.toString(); } } // Override default methods in Collection @Override public void forEach(java.util.function.Consumer consumer) { synchronized (mutex) { c.forEach(consumer); } } @Override public boolean removeIf(java.util.function.Predicate filter) { synchronized (mutex) { return c.removeIf(filter); } } @Override public Spliterator spliterator() { // Must be manually synched by user! return c.spliterator(); } @Override public java.util.stream.Stream stream() { // Must be manually synched by user! return c.stream(); } @Override public java.util.stream.Stream parallelStream() { // Must be manually synched by user! return c.parallelStream(); } @java.io.Serial private void writeObject(ObjectOutputStream s) throws IOException { synchronized (mutex) { s.defaultWriteObject(); } } } // the lockFile must be a file separate from any data files. // It is created & deleted by this class, and will always have // size 0. static class FileBasedLock implements AutoCloseable { File lockFile; // in seconds. refresh happens twice as often double timeout = 60.0; boolean verbose = false; boolean haveLock = false; java.util.Timer touchTimer; FileBasedLock() { } FileBasedLock(File lockFile) { this.lockFile = lockFile; } FileBasedLock(File lockFile, double timeout) { this.timeout = timeout; this.lockFile = lockFile; } // returns true iff lock was acquired (or kept) synchronized boolean tryToLock() { if (haveLock) return true; if (fileExists(lockFile)) { double age = fileAgeInSeconds(lockFile); if (verbose) print("Lock file age: " + lockFile + " = " + iround(age) + " s"); if (age >= timeout) { print("Deleting old lock file (program crashed?): " + lockFile + " (age: " + iround(age) + " seconds)"); deleteFile(lockFile); } } try { mkdirsForFile(lockFile); java.nio.file.Files.createFile(toPath(lockFile)); acquired(); return true; } catch (Throwable e) { printExceptionShort("Can't lock", e); return false; } } private void acquired() { haveLock = true; startTouchTimer(); } void forceLock() { try { print("Force-locking " + lockFile); // make or touch file touchFile(lockFile); acquired(); } catch (Exception __e) { throw rethrow(__e); } } String lockError() { return "Couldn't aquire lock file: " + lockFile; } void lockOrFail() { if (!tryToLock()) throw fail(lockError()); } synchronized void startTouchTimer() { if (touchTimer != null) return; double interval = timeout / 2; touchTimer = doEvery(interval, new Runnable() { public void run() { try { doTouch(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "doTouch();"; } }); if (verbose) print("Touch timer started for " + lockFile + " (" + interval + "s)"); } synchronized void doTouch() { try { if (haveLock) { if (verbose) print("Touching lock file: " + lockFile); touchExistingFile(lockFile); } } catch (Throwable __e) { _handleException(__e); } } public synchronized void close() { try { { cleanUp(touchTimer); touchTimer = null; } if (haveLock) { haveLock = false; if (verbose) print("Deleting lock file: " + lockFile); deleteFile(lockFile); } } catch (Throwable __e) { _handleException(__e); } } synchronized void _simulateCrash() { { cleanUp(touchTimer); touchTimer = null; } } } static interface IConceptCounter { Class conceptClass(); int countConcepts(); Collection allConcepts(); } // uses HashMap by default static class MultiSet { Map map = new HashMap(); // now maintaining a size counter int size; MultiSet(boolean useTreeMap) { if (useTreeMap) map = new TreeMap(); } MultiSet() { } MultiSet(Iterable c) { addAll(c); } MultiSet(MultiSet ms) { synchronized (ms) { for (A a : ms.keySet()) add(a, ms.get(a)); } } // returns new count synchronized int add(A key) { return add(key, 1); } synchronized void addAll(Iterable c) { if (c != null) for (A a : c) add(a); } synchronized void addAll(MultiSet ms) { for (A a : ms.keySet()) add(a, ms.get(a)); } synchronized int add(A key, int count) { // don't calculate return value in this case if (count <= 0) return 0; size += count; Integer i = map.get(key); map.put(key, i != null ? (count += i) : count); return count; } synchronized void put(A key, int count) { int oldCount = get(key); if (count == oldCount) return; size += count - oldCount; if (count != 0) map.put(key, count); else map.remove(key); } synchronized int get(A key) { Integer i = map.get(key); return i != null ? i : 0; } synchronized boolean contains(A key) { return map.containsKey(key); } synchronized void remove(A key) { Integer i = map.get(key); if (i != null) { --size; if (i > 1) map.put(key, i - 1); else map.remove(key); } } synchronized List topTen() { return getTopTen(); } synchronized List getTopTen() { return getTopTen(10); } synchronized List getTopTen(int maxSize) { List list = getSortedListDescending(); return list.size() > maxSize ? list.subList(0, maxSize) : list; } synchronized List highestFirst() { return getSortedListDescending(); } synchronized List lowestFirst() { return reversedList(getSortedListDescending()); } synchronized List getSortedListDescending() { List list = new ArrayList(map.keySet()); Collections.sort(list, new Comparator() { public int compare(A a, A b) { return map.get(b).compareTo(map.get(a)); } }); return list; } synchronized int getNumberOfUniqueElements() { return map.size(); } synchronized int uniqueSize() { return map.size(); } synchronized Set asSet() { return map.keySet(); } synchronized NavigableSet navigableSet() { return navigableKeys((NavigableMap) map); } synchronized Set keySet() { return map.keySet(); } synchronized A getMostPopularEntry() { int max = 0; A a = null; for (Map.Entry entry : map.entrySet()) { if (entry.getValue() > max) { max = entry.getValue(); a = entry.getKey(); } } return a; } synchronized void removeAll(A key) { size -= get(key); map.remove(key); } synchronized int size() { return size; } synchronized MultiSet mergeWith(MultiSet set) { MultiSet result = new MultiSet(); for (A a : set.asSet()) { result.add(a, set.get(a)); } return result; } synchronized boolean isEmpty() { return map.isEmpty(); } synchronized public String toString() { // hmm. sync this? return str(map); } synchronized void clear() { map.clear(); size = 0; } synchronized Map asMap() { return cloneMap(map); } } static class RemoteDB implements AutoCloseable { DialogIO db; String name; // s = bot name or snippet ID RemoteDB(String s) { this(s, false); } RemoteDB(String s, boolean autoStart) { name = s; if (isSnippetID(s)) name = dbBotName(s); db = findBot(name); if (db == null) if (autoStart) { nohupJavax(fsI(s)); waitForBotStartUp(name); assertNotNull("Weird problem", db = findBot(s)); } else throw fail("DB " + s + " not running"); } // now always true boolean functional() { return db != null; } List list() { return adopt((List) rpc(db, "xlist")); } List list(String className) { return adopt((List) rpc(db, "xlist", className)); } List xlist() { return list(); } List xlist(String className) { return list(className); } // adopt is an internal method List adopt(List l) { if (l != null) for (RC rc : l) adopt(rc); return l; } RC adopt(RC rc) { if (rc != null) rc.db = this; return rc; } Object adopt(Object o) { if (o instanceof RC) return adopt((RC) o); return o; } String xclass(RC o) { return (String) rpc(db, "xclass", o); } Object xget(RC o, String field) { return adopt(rpc(db, "xget", o, field)); } String xS(RC o, String field) { return (String) xget(o, field); } RC xgetref(RC o, String field) { return adopt((RC) xget(o, field)); } void xset(RC o, String field, Object value) { rpc(db, "xset", o, field, value); } RC uniq(String className) { RC ref = first(list(className)); if (ref == null) ref = xnew(className); return ref; } RC xuniq(String className) { return uniq(className); } RC xnew(String className, Object... values) { return adopt((RC) rpc(db, "xnew", className, values)); } void xdelete(RC o) { rpc(db, "xdelete", o); } void xdelete(List l) { rpc(db, "xdelete", l); } public void close() { _close(db); } String fullgrab() { return (String) rpc(db, "xfullgrab"); } String xfullgrab() { return fullgrab(); } void xshutdown() { rpc(db, "xshutdown"); } long xchangeCount() { return (long) rpc(db, "xchangeCount"); } int xcount() { return (int) rpc(db, "xcount"); } void reconnect() { close(); db = findBot(name); } RC rc(long id) { return new RC(this, id); } } static class FontMetricsWrapper extends FontMetrics { FontMetrics target; FontMetricsWrapper(FontMetrics target) { super(target.getFont()); this.target = target; } @Override public Font getFont() { return target.getFont(); } @Override public FontRenderContext getFontRenderContext() { return target.getFontRenderContext(); } @Override public int getLeading() { return target.getLeading(); } @Override public int getAscent() { return target.getAscent(); } @Override public int getDescent() { return target.getDescent(); } @Override public int getHeight() { return target.getHeight(); } @Override public int getMaxAscent() { return target.getMaxAscent(); } @Override public int getMaxDescent() { return target.getMaxDescent(); } @Override @Deprecated public int getMaxDecent() { return target.getMaxDecent(); } @Override public int getMaxAdvance() { return target.getMaxAdvance(); } @Override public int charWidth(int codePoint) { return target.charWidth(codePoint); } @Override public int charWidth(char ch) { return target.charWidth(ch); } @Override public int stringWidth(String str) { return target.stringWidth(str); } @Override public int charsWidth(char[] data, int off, int len) { return target.charsWidth(data, off, len); } @Override public int bytesWidth(byte[] data, int off, int len) { return target.bytesWidth(data, off, len); } @Override public int[] getWidths() { return target.getWidths(); } @Override public boolean hasUniformLineMetrics() { return target.hasUniformLineMetrics(); } @Override public LineMetrics getLineMetrics(String str, Graphics context) { return target.getLineMetrics(str, context); } @Override public LineMetrics getLineMetrics(String str, int beginIndex, int limit, Graphics context) { return target.getLineMetrics(str, beginIndex, limit, context); } @Override public LineMetrics getLineMetrics(char[] chars, int beginIndex, int limit, Graphics context) { return target.getLineMetrics(chars, beginIndex, limit, context); } @Override public LineMetrics getLineMetrics(java.text.CharacterIterator ci, int beginIndex, int limit, Graphics context) { return target.getLineMetrics(ci, beginIndex, limit, context); } @Override public Rectangle2D getStringBounds(String str, Graphics context) { return target.getStringBounds(str, context); } @Override public Rectangle2D getStringBounds(String str, int beginIndex, int limit, Graphics context) { return target.getStringBounds(str, beginIndex, limit, context); } @Override public Rectangle2D getStringBounds(char[] chars, int beginIndex, int limit, Graphics context) { return target.getStringBounds(chars, beginIndex, limit, context); } @Override public Rectangle2D getStringBounds(java.text.CharacterIterator ci, int beginIndex, int limit, Graphics context) { return target.getStringBounds(ci, beginIndex, limit, context); } @Override public Rectangle2D getMaxCharBounds(Graphics context) { return target.getMaxCharBounds(context); } @Override public String toString() { return target.toString(); } } static Lock dbLock() { return db_mainConcepts().lock; } static Lock dbLock(Concepts cc) { return cc == null ? null : cc.lock; } static Lock dbLock(Concept c) { return dbLock(c == null ? null : c._concepts); } static boolean bareDBMode_on = false; static void bareDBMode() { // default autoSaveInterval bareDBMode(null); } static void bareDBMode(Integer autoSaveInterval) { bareDBMode_on = true; conceptsAndBot(autoSaveInterval); } static Border getBorder(final JComponent c) { return c == null ? null : swing(new F0() { public Border get() { try { return c.getBorder(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getBorder();"; } }); } static float clamp(float x, float a, float b) { return x < a ? a : x > b ? b : x; } static double clamp(double x, double a, double b) { return x < a ? a : x > b ? b : x; } static int clamp(int x, int a, int b) { return x < a ? a : x > b ? b : x; } static void add(BitSet bs, int i) { bs.set(i); } static boolean add(Collection c, A a) { return c != null && c.add(a); } static void add(Container c, Component x) { addToContainer(c, x); } static A _print(String s, A a) { return print(s, a); } static A _print(A a) { return print(a); } static void _print() { print(); } static boolean _eq(Object a, Object b) { return eq(a, b); } static String toString(Object o) { return strOrNull(o); } static String formatDouble(double d, int digits) { String format = digits <= 0 ? "0" : "0." + rep(digits, '#'); return decimalFormatEnglish(format, d); } static double ratioToPercent(double x, double y) { return x * 100 / y; } static float score(Scored s) { return s == null ? 0 : s.score(); } static Class _run(String progID, String... args) { Class main = hotwire(progID); callMain(main, args); return main; } static A getWeakRef(Reference ref) { return ref == null ? null : ref.get(); } static void setComponent(SingleComponentPanel scp, Component c) { setSCPComponent(scp, c); } static void setComponent(SingleComponentPanel scp, IF0 c) { if (scp != null) setComponent(scp, callF(c)); } static void removeAll(Collection a, Collection b) { if (a != null && b != null) a.removeAll(b); } static void removeAll(Map a, Collection b) { if (a != null && b != null) for (A x : b) a.remove(x); } static boolean removeAll(Collection c, B... b) { return c != null && b != null && c.removeAll(Arrays.asList(b)); } static void removeAll(Map a, A... b) { if (a != null && b != null) for (A x : b) a.remove(x); } static A _revalidate(A c) { return revalidate(c); } static void _revalidate(JFrame f) { revalidate(f); } static void _revalidate(JInternalFrame f) { revalidate(f); } static Container _getParent(Component c) { return getParent(c); } static List getAll(Map map, Collection l) { return lookupAllOpt(map, l); } static List getAll(Collection l, Map map) { return lookupAllOpt(map, l); } static boolean hasConcept(Class c, Object... params) { return findConceptWhere(c, params) != null; } static Object load(String varName) { readLocally(varName); return get(mc(), varName); } static Object load(String progID, String varName) { readLocally(progID, varName); return get(mc(), varName); } static boolean exceptionMessageContains(Throwable e, String s) { return cic(getInnerMessage(e), s); } static void printShortException(Throwable e) { print(exceptionToStringShort(e)); } static void printShortException(String s, Throwable e) { print(s, exceptionToStringShort(e)); } static void clearConcepts() { db_mainConcepts().clearConcepts(); } static void clearConcepts(Concepts concepts) { concepts.clearConcepts(); } static void restoreLatestBackupIfConceptsFileEmpty(String dbID, Object... __) { boolean doIt = boolPar("doIt", __); File file = conceptsFile(dbID); if (fileExists(file) && fileSize(file) == 0) { print(file + " corrupted, trying to restore"); File backup = lastThat(__47 -> fileNotEmpty(__47), sortByFileName(conceptBackupFiles(dbID))); if (backup == null) { print("No usable backup found :("); return; } String msg = "RESTORING: " + backup; File log = javaxDataDir("db-restores.log"); if (doIt) logQuotedWithTime(log, msg); print(stringIf(!doIt, "[would be] ") + msg); if (doIt) { clearConceptsOf(dbID); copyFile(backup, file); print(msg = "DB RESTORED!"); if (doIt) logQuotedWithTime(log, msg); } } } static void readLocally(String progID, String varNames) { readLocally2(mc(), progID, varNames); } static void readLocally(String varNames) { readLocally2(mc(), programID(), varNames); } static void readLocally2(Object obj, String varNames) { readLocally2(obj, programID(), varNames); } static int readLocally_stringLength; static ThreadLocal readLocally2_allDynamic = new ThreadLocal(); static ThreadLocal readLocally2_classFinder = new ThreadLocal(); // read a string variable from standard storage // does not overwrite variable contents if there is no file static void readLocally2(Object obj, String progID, String varNames) { try { boolean allDynamic = isTrue(getAndClearThreadLocal(readLocally2_allDynamic)); for (String variableName : javaTokC(varNames)) { File textFile = new File(programDir(progID), variableName + ".text"); String value = loadTextFile(textFile); if (value != null) set(main.class, variableName, value); else { File structureFile = new File(programDir(progID), variableName + ".structure"); value = loadTextFile(structureFile); if (value == null) { File structureGZFile = new File(programDir(progID), variableName + ".structure.gz"); if (!structureGZFile.isFile()) return; // value = loadGZTextFile(structureGZFile); InputStream fis = new FileInputStream(structureGZFile); try { GZIPInputStream gis = newGZIPInputStream(fis); InputStreamReader reader = new InputStreamReader(gis, "UTF-8"); BufferedReader bufferedReader = new BufferedReader(reader); // O o = unstructure_reader(bufferedReader); Object o = unstructure_tok(javaTokC_noMLS_onReader(bufferedReader), allDynamic, readLocally2_classFinder.get()); readLocally_set(obj, variableName, o); return; } finally { _close(fis); } } readLocally_stringLength = l(value); if (nempty(value)) readLocally_set(obj, variableName, unstructure(value, allDynamic, readLocally2_classFinder.get())); } } } catch (Exception __e) { throw rethrow(__e); } } static void readLocally_set(Object c, String varName, Object value) { Object oldValue = get(c, varName); if (oldValue instanceof List && !(oldValue instanceof ArrayList) && value != null) { // Assume it's a synchroList. value = synchroList((List) value); } set(c, varName, value); } static int done_minPrint = 10; static long done(long startTime, String desc) { long time = now() - startTime; if (time >= done_minPrint) print(desc + " [" + time + " ms]"); return time; } static long done(String desc, long startTime) { return done(startTime, desc); } static long done(long startTime) { return done(startTime, ""); } static RemoteDB connectToDBOpt(String dbNameOrID) { try { return new RemoteDB(dbNameOrID); } catch (Throwable __e) { return null; } } static List> mapToPairs(Map map) { List> l = emptyList(l(map)); if (map != null) for (Map.Entry e : map.entrySet()) l.add(pair(e.getKey(), e.getValue())); return l; } static String dynShortName(Object o) { return shortDynamicClassName(o); } static Concept getConcept(long id) { return db_mainConcepts().getConcept(id); } static Concept getConcept(Concepts concepts, long id) { return concepts.getConcept(id); } static A getConcept(Class cc, long id) { return getConcept(db_mainConcepts(), cc, id); } static A getConcept(Concepts concepts, Class cc, long id) { Concept c = concepts.getConcept(id); if (c == null) return null; if (!isInstance(cc, c)) throw fail("Can't convert concept: " + getClassName(c) + " -> " + getClassName(cc) + " (" + id + ")"); return (A) c; } static void saveLocally(String variableName) { saveLocally(programID(), variableName); } static void saveLocally(String progID, String variableName) { saveLocally2(mc(), progID, variableName); } static void saveLocally2(Object obj, String variableName) { saveLocally2(obj, programID(), variableName); } static File saveLocally2(Object obj, String progID, String variableName) { Lock __0 = saveLock(); lock(__0); try { File textFile = new File(programDir(progID), variableName + ".text"); File structureFile = new File(programDir(progID), variableName + ".structure"); Object x = get(obj, variableName); if (x == null) { textFile.delete(); structureFile.delete(); return null; } else if (x instanceof String) { saveTextFile(textFile, (String) x); structureFile.delete(); return textFile; } else { saveTextFile(structureFile, javaTokWordWrap(structure(x))); textFile.delete(); return structureFile; } } finally { unlock(__0); } } static File conceptsFile(String progID) { return getProgramFile(progID, conceptsFileName()); } static File conceptsFile() { return conceptsFile(dbProgramID()); } // wrapper: VF1 or null static void callRunnableWithWrapper(Object wrapper, Runnable r) { if (wrapper == null) callF(r); else callF(wrapper, r); } static List callFAll(Collection l, Object... args) { return callF_all(l, args); } static long saveGZStructureToFile(String file, Object o) { return saveGZStructureToFile(getProgramFile(file), o); } // returns number of uncompressed bytes written static long saveGZStructureToFile(File file, Object o) { return saveGZStructureToFile(file, o, new structure_Data()); } static long saveGZStructureToFile(File file, Object o, structure_Data data) { try { File parentFile = file.getParentFile(); if (parentFile != null) parentFile.mkdirs(); File tempFile = tempFileFor(file); if (tempFile.exists()) try { String saveName = tempFile.getPath() + ".saved." + now(); copyFile(tempFile, new File(saveName)); } catch (Throwable e) { printStackTrace(e); } FileOutputStream fileOutputStream = newFileOutputStream(tempFile.getPath()); CountingOutputStream cos; try { GZIPOutputStream gos = new GZIPOutputStream(fileOutputStream); cos = new CountingOutputStream(gos); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(cos, "UTF-8"); PrintWriter printWriter = new PrintWriter(outputStreamWriter); structureToPrintWriter(o, printWriter, data); printWriter.close(); gos.close(); fileOutputStream.close(); } catch (Throwable e) { fileOutputStream.close(); tempFile.delete(); throw rethrow(e); } if (file.exists() && !file.delete()) throw new IOException("Can't delete " + file.getPath()); if (!tempFile.renameTo(file)) throw new IOException("Can't rename " + tempFile + " to " + file); return cos.getFilePointer(); } catch (Exception __e) { throw rethrow(__e); } } static long toM(long l) { return (l + 1024 * 1024 - 1) / (1024 * 1024); } static String toM(long l, int digits) { return formatDouble(toM_double(l), digits); } static String javaTokWordWrap(String s) { return javaTokWordWrap(120, s); } // TODO: complete trimming static String javaTokWordWrap(int cols, String s) { int col = 0; List tok = javaTok(s); for (int i = 0; i < l(tok); i++) { String t = tok.get(i); if (odd(i) && col >= cols && !containsNewLine(t)) tok.set(i, t = rtrimSpaces(t) + "\n"); int idx = t.lastIndexOf('\n'); if (idx >= 0) col = l(t) - (idx + 1); else col += l(t); } return join(tok); } static String ymd() { return ymd(now()); } static String ymd(long now) { return year(now) + formatInt(month(now), 2) + formatInt(dayOfMonth(now), 2); } static String ymd(long now, TimeZone tz) { return year(now, tz) + formatInt(month(now, tz), 2) + formatInt(dayOfMonth(now, tz), 2); } static String formatInt(int i, int digits) { return padLeft(str(i), '0', digits); } static String formatInt(long l, int digits) { return padLeft(str(l), '0', digits); } static int hours() { return hours(java.util.Calendar.getInstance()); } static int hours(java.util.Calendar c) { return c.get(java.util.Calendar.HOUR_OF_DAY); } static int hours(long time) { return hours(calendarFromTime(time)); } static int hours(long time, TimeZone tz) { return hours(calendarFromTime(time, tz)); } static long toK(long l) { return (l + 1023) / 1024; } static long sysNow() { ping(); return System.nanoTime() / 1000000; } // firstDelay = delay static FixedRateTimer doEvery_daemon(long delay, final Object r) { return doEvery_daemon(delay, delay, r); } static FixedRateTimer doEvery_daemon(long delay, long firstDelay, final Object r) { FixedRateTimer timer = new FixedRateTimer(true); timer.scheduleAtFixedRate(smartTimerTask(r, timer, delay), firstDelay, delay); return timer; } static FixedRateTimer doEvery_daemon(double delaySeconds, final Object r) { return doEvery_daemon(toMS(delaySeconds), r); } static float abs(float f) { return Math.abs(f); } static int abs(int i) { return Math.abs(i); } static double abs(double d) { return Math.abs(d); } static A firstOfType(Collection c, Class type) { for (Object x : c) if (isInstanceX(type, x)) return (A) x; return null; } static Collection allConcepts() { return db_mainConcepts().allConcepts(); } static Collection allConcepts(Concepts concepts) { return concepts.allConcepts(); } static List conceptsOfType(String type) { return db_mainConcepts().conceptsOfType(type); } static List concatLists_conservative(List a, List b) { if (empty(a)) return b; if (empty(b)) return a; return concatLists(a, b); } static List concatLists_conservative(Collection a, Collection b) { if (empty(a) && b instanceof List) return ((List) b); if (empty(b) && a instanceof List) return ((List) a); return concatLists(a, b); } static List filterByType(Iterable c, Class type) { List l = new ArrayList(); if (c != null) for (Object x : c) if (isInstanceX(type, x)) l.add((A) x); return l; } static List filterByType(Object[] c, Class type) { return filterByType(asList(c), type); } static List filterByType(Class type, Iterable c) { return filterByType(c, type); } static List filterByDynamicType(Collection c, String type) { List l = new ArrayList(); for (A x : c) if (eq(dynamicClassName(x), type)) l.add(x); return l; } static boolean hasType(Collection c, Class type) { for (Object x : c) if (isInstanceX(type, x)) return true; return false; } static A findBackRef(Concept c, Class type) { for (Concept.Ref r : c.backRefs) if (instanceOf(r.concept(), type)) return (A) r.concept(); return null; } static A findBackRef(Class type, Concept c) { return findBackRef(c, type); } static String loadConceptsStructure(String progID) { return loadTextFilePossiblyGZipped(getProgramFile(progID, "concepts.structure")); } static String loadConceptsStructure() { return loadConceptsStructure(dbProgramID()); } static int countConcepts(Concepts concepts, Class c, Object... params) { return concepts.countConcepts(c, params); } static int countConcepts(Class c, Object... params) { return db_mainConcepts().countConcepts(c, params); } static int countConcepts() { return db_mainConcepts().countConcepts(); } static int countConcepts(String className) { return db_mainConcepts().countConcepts(className); } static int countConcepts(Concepts concepts, String className) { return concepts.countConcepts(className); } static int countConcepts(Concepts concepts) { return concepts.countConcepts(); } static void mapRemove(Map map, A key) { if (map != null && key != null) map.remove(key); } static boolean containsKey(Map map, A key) { return map != null && map.containsKey(key); } static boolean syncAdd(Collection c, A b) { if (c == null) return false; synchronized (collectionMutex(c)) { return c.add(b); } } static void syncAdd(List l, int idx, A b) { if (l != null) synchronized (collectionMutex(l)) { l.add(idx, b); } } static boolean syncRemove(Collection c, A b) { if (c == null) return false; synchronized (collectionMutex(c)) { return c.remove(b); } } static A syncRemove(List l, int idx) { if (l == null) return null; synchronized (collectionMutex(l)) { return l.remove(idx); } } static B syncRemove(Map map, A key) { return map == null ? null : map.remove(key); } static List syncAddOrCreate(List l, A a) { if (l == null) l = syncList(); l.add(a); return l; } static boolean dynamicObjectIsLoading() { return isTrue(getThreadLocal(DynamicObject_loading)); } static Str concept(String name) { for (Str s : list(Str.class)) if (eqic(s.name, name) || containsIgnoreCase(s.otherNames, name)) return s; return new Str(name); } static boolean isEmpty(Collection c) { return c == null || c.isEmpty(); } static boolean isEmpty(CharSequence s) { return s == null || s.length() == 0; } static boolean isEmpty(Object[] a) { return a == null || a.length == 0; } static boolean isEmpty(byte[] a) { return a == null || a.length == 0; } static boolean isEmpty(Map map) { return map == null || map.isEmpty(); } static void removeLast(List l) { if (!l.isEmpty()) l.remove(l(l) - 1); } static void removeLast(List l, int n) { removeSubList(l, l(l) - n); } static void removeLast(int n, List l) { removeLast(l, n); } static A syncGet(List l, int idx) { if (l == null || idx < 0) return null; synchronized (l) { return idx < l(l) ? l.get(idx) : null; } } static B syncGet(Map map, A a) { if (map == null) return null; synchronized (map) { return map.get(a); } } static int syncL(Collection l) { if (l == null) return 0; synchronized (l) { return l.size(); } } static List syncL() { return syncList(); } static List addDyn_quickSync(List l, A a) { if (l == null) l = new ArrayList(); syncAdd(l, a); return l; } static List removeDyn_quickSync(List l, A a) { if (l == null) return null; synchronized (collectionMutex(l)) { l.remove(a); return empty(l) ? null : l; } } static void crenameField_noOverwrite(Concept c, String oldField, String newField) { if (c == null || eq(oldField, newField)) return; Object value = cget(c, oldField); if (newField != null && cget(c, newField) == null) cset(c, newField, value); cset(c, oldField, null); } static Collection scanConceptForRefs(Concept c) { Set refs = new HashSet(); if (c != null) for (Object o : values(objectToMap(c))) { if (o instanceof Concept.Ref) refs.add(((Concept.Ref) o)); else if (o instanceof Concept.RefL) addAll(refs, ((Concept.RefL) o).l); } return refs; } static boolean stdEq2(Object a, Object b) { if (a == null) return b == null; if (b == null) return false; if (a.getClass() != b.getClass()) return false; for (String field : allFields(a)) if (neq(getOpt(a, field), getOpt(b, field))) return false; return true; } static int stdHash2(Object a) { if (a == null) return 0; return stdHash(a, toStringArray(allFields(a))); } static String firstToUpper(String s) { if (empty(s)) return s; return Character.toUpperCase(s.charAt(0)) + s.substring(1); } static long stopTiming_defaultMin = 10; static long startTiming_startTime; static void startTiming() { startTiming_startTime = now(); } static void stopTiming() { stopTiming(null); } static void stopTiming(String text) { stopTiming(text, stopTiming_defaultMin); } static void stopTiming(String text, long minToPrint) { long time = now() - startTiming_startTime; if (time >= minToPrint) { text = or2(text, "Time: "); print(text + time + " ms"); } } static UnsupportedOperationException unsupportedOperation() { throw new UnsupportedOperationException(); } static ListIterator listIterator(List l) { return l == null ? emptyListIterator() : l.listIterator(); } static boolean isAbstract(Class c) { return (c.getModifiers() & Modifier.ABSTRACT) != 0; } static boolean isAbstract(Method m) { return (m.getModifiers() & Modifier.ABSTRACT) != 0; } static Set allInterfacesImplementedBy(Class c) { if (c == null) return null; HashSet set = new HashSet(); allInterfacesImplementedBy_find(c, set); return set; } static void allInterfacesImplementedBy_find(Class c, Set set) { if (c.isInterface() && !set.add(c)) return; do { for (Class intf : c.getInterfaces()) allInterfacesImplementedBy_find(intf, set); } while ((c = c.getSuperclass()) != null); } static Method findStaticMethod(Class c, String method, Object... args) { Class _c = c; while (c != null) { for (Method m : c.getDeclaredMethods()) { if (!m.getName().equals(method)) continue; if ((m.getModifiers() & Modifier.STATIC) == 0 || !findStaticMethod_checkArgs(m, args)) continue; return m; } c = c.getSuperclass(); } return null; } static boolean findStaticMethod_checkArgs(Method m, Object[] args) { Class[] types = m.getParameterTypes(); if (types.length != args.length) return false; for (int i = 0; i < types.length; i++) if (!(args[i] == null || isInstanceX(types[i], args[i]))) return false; return true; } static String dropTrailingBackslashR(String s) { int i = l(s); while (i > 0 && s.charAt(i - 1) == '\r') --i; return substring(s, 0, i); } static List quoteAll(Collection l) { List x = new ArrayList(); for (String s : l) x.add(quote(s)); return x; } static boolean arraysEqual(Object[] a, Object[] b) { if (a.length != b.length) return false; for (int i = 0; i < a.length; i++) if (neq(a[i], b[i])) return false; return true; } static A syncPopFirst(List l) { if (empty(l)) return null; synchronized (l) { A a = first(l); l.remove(0); return a; } } static Set keySet(Map map) { return map == null ? new HashSet() : map.keySet(); } static Set keySet(Object map) { return keys((Map) map); } static Set keySet(MultiSet ms) { return ms.keySet(); } static Set> entrySet(Map map) { return _entrySet(map); } // TODO: use actualUserHome()? // (there was a problem with onLocallyInferiorJavaX() always triggering inside #1013896) static File pathToJavaxJar() { IResourceLoader rl = vm_getResourceLoader(); if (rl != null) return rl.pathToJavaXJar(); return pathToJavaxJar_noResourceLoader(); } static File pathToJavaxJar_noResourceLoader() { try { int x = latestInstalledJavaX(); File xfile = new File(userHome(), ".javax/x" + Math.max(x, 30) + ".jar"); if (!xfile.isFile()) { print("Saving " + f2s(xfile)); String url = x30JarServerURL(); byte[] data = loadBinaryPage(url); if (data.length < 1000000) throw fail("Could not load " + url); saveBinaryFile(xfile.getPath(), data); } return xfile; } catch (Exception __e) { throw rethrow(__e); } } static String b(Object contents, Object... params) { return tag("b", contents, params); } static boolean isA(Either e) { return eitherIsA(e); } static int hashCodeFor(Object a) { return a == null ? 0 : a.hashCode(); } static A setToolTipText(final A c, final Object toolTip) { if (c == null) return null; { swing(new Runnable() { public void run() { try { String s = nullIfEmpty(str(toolTip)); if (neq(s, c.getToolTipText())) c.setToolTipText(s); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "String s = nullIfEmpty(str(toolTip));\r\n if (neq(s, c.getToolTipText()))\r\n ..."; } }); } return c; } static A setToolTipText(Object toolTip, A c) { return setToolTipText(c, toolTip); } static String nullIfEmpty(String s) { return isEmpty(s) ? null : s; } static Map nullIfEmpty(Map map) { return isEmpty(map) ? null : map; } static List nullIfEmpty(List l) { return isEmpty(l) ? null : l; } static LinkedHashMap cloneLinkedHashMap(Map map) { return map == null ? new LinkedHashMap() : new LinkedHashMap(map); } static A second(List l) { return get(l, 1); } static A second(Iterable l) { if (l == null) return null; Iterator it = iterator(l); if (!it.hasNext()) return null; it.next(); return it.hasNext() ? it.next() : null; } static A second(A[] bla) { return bla == null || bla.length <= 1 ? null : bla[1]; } static B second(Pair p) { return p == null ? null : p.b; } static A second(Producer p) { if (p == null) return null; if (p.next() == null) return null; return p.next(); } static char second(String s) { return charAt(s, 1); } static B second(Either e) { return e == null ? null : e.bOpt(); } // fromKey = inclusive, toKey = exclusive static SortedMap subMap(SortedMap map, A fromKey, A toKey) { return map == null ? null : map.subMap(fromKey, toKey); } static A firstKey(Map map) { return first(keys(map)); } static A lastKey(SortedMap map) { return empty(map) ? null : map.lastKey(); } static List diff(Collection a, Collection b) { Set set = asSet(b); List l = new ArrayList(); for (String s : a) if (!set.contains(s)) l.add(s); return l; } static double fileAgeInSeconds(File f) { return f == null ? -1 : msToSeconds(now() - fileModificationTime(f)); } static boolean deleteFile(File file) { return file != null && file.delete(); } static Path toPath(File f) { return f == null ? null : f.toPath(); } static void printExceptionShort(Throwable e) { printExceptionShort("", e); } static void printExceptionShort(String prefix, Throwable e) { print(prefix, exceptionToStringShort(e)); } // will create the file or update its last modified timestamp static void touchFile(File file) { try { closeRandomAccessFile(newRandomAccessFile(mkdirsForFile(file), "rw")); } catch (Exception __e) { throw rethrow(__e); } } // firstDelay = delay static FixedRateTimer doEvery(long delay, final Object r) { return doEvery(delay, delay, r); } static FixedRateTimer doEvery(long delay, long firstDelay, final Object r) { FixedRateTimer timer = new FixedRateTimer(shorten(programID() + ": " + r, 80)); timer.scheduleAtFixedRate(smartTimerTask(r, timer, toInt(delay)), toInt(firstDelay), toInt(delay)); return vmBus_timerStarted(timer); } // reversed argument order for fun static FixedRateTimer doEvery(double initialSeconds, double delaySeconds, final Object r) { return doEvery(toMS(delaySeconds), toMS(initialSeconds), r); } static FixedRateTimer doEvery(double delaySeconds, final Object r) { return doEvery(toMS(delaySeconds), r); } static void touchExistingFile(File file) { try { if (file == null) return; java.nio.file.Files.setLastModifiedTime(toPath(file), java.nio.file.attribute.FileTime.from(java.time.Instant.now())); } catch (Exception __e) { throw rethrow(__e); } } static Set asSet(Object[] array) { HashSet set = new HashSet(); for (Object o : array) if (o != null) set.add(o); return set; } static Set asSet(String[] array) { TreeSet set = new TreeSet(); for (String o : array) if (o != null) set.add(o); return set; } static Set asSet(Iterable l) { if (l instanceof Set) return (Set) l; HashSet set = new HashSet(); for (A o : unnull(l)) if (o != null) set.add(o); return set; } // Note: does not clone the set (keeps multiset alive) static Set asSet(MultiSet ms) { return ms == null ? null : ms.asSet(); } static NavigableSet navigableKeys(NavigableMap map) { return map == null ? new TreeSet() : map.navigableKeySet(); } static NavigableSet navigableKeys(MultiSet ms) { return ((NavigableMap) ms.map).navigableKeySet(); } static long waitForBotStartUp_timeoutSeconds = 60; // returns address or fails static String waitForBotStartUp(String botName) { for (int i = 0; i < waitForBotStartUp_timeoutSeconds; i++) { sleepSeconds(i == 0 ? 0 : 1); String addr = getBotAddress(botName); if (addr != null) return addr; } throw fail("Bot not found: " + quote(botName)); } static Object rpc(String botName, String method, Object... args) { return unstructure_matchOK2OrFail(sendToLocalBot(botName, rpc_makeCall(method, args))); } static Object rpc(DialogIO bot, String method, Object... args) { return unstructure_matchOK2OrFail(bot.ask(rpc_makeCall(method, args))); } static String rpc_makeCall(String method, Object... args) { if (empty(args)) return "call " + method; return format("call *", concatLists((List) ll(method), asList(args))); } static void close(AutoCloseable c) { _close(c); } static Font getFont(JComponent c) { return c == null ? null : swing(new F0() { public Font get() { try { return c.getFont(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getFont();"; } }); } static String decimalFormatEnglish(String format, double d) { return decimalFormatEnglish(format).format(d); } static java.text.DecimalFormat decimalFormatEnglish(String format) { return new java.text.DecimalFormat(format, new java.text.DecimalFormatSymbols(Locale.ENGLISH)); } static void setSCPComponent(SingleComponentPanel scp, Component c) { if (scp != null) scp.setComponent(c); } static Container getParent(final Component c) { return c == null ? null : swing(new F0() { public Container get() { try { return c.getParent(); } catch (Exception __e) { throw rethrow(__e); } } public String toString() { return "ret c.getParent();"; } }); } static List lookupAllOpt(Map map, Collection l) { List out = new ArrayList(); if (l != null) for (A a : l) addIfNotNull(out, map.get(a)); return out; } static List lookupAllOpt(Collection l, Map map) { return lookupAllOpt(map, l); } static boolean cic(Collection l, String s) { return containsIgnoreCase(l, s); } static boolean cic(String[] l, String s) { return containsIgnoreCase(l, s); } static boolean cic(String s, char c) { return containsIgnoreCase(s, c); } static boolean cic(String a, String b) { return containsIgnoreCase(a, b); } static A lastThat(List l, Object pred) { for (int i = l(l) - 1; i >= 0; i--) { A a = l.get(i); if (checkCondition(pred, a)) return a; } return null; } static A lastThat(Object pred, List l) { return lastThat(l, pred); } static A lastThat(IF1 pred, List l) { return lastThat((Object) pred, l); } static A lastThat(List l, IF1 pred) { return lastThat(pred, l); } static boolean fileNotEmpty(File f) { return isFile(f) && fileSize(f) > 0; } static List sortByFileName(List l) { return sortFilesByName(l); } // sorted by descending date static List conceptBackupFiles(String progID) { String regexp = "^(.*)\\.backup(20\\d\\d)(\\d\\d)(\\d\\d)-(\\d\\d)$"; File dir = programDir(progID); List l = new ArrayList(); for (File f : listFilesNotDirs(dir, newFile(dir, "backups"))) { String s = f.getName(); String originalName = regexpFirstGroup(regexp, s); { if (!(eq(originalName, "concepts.structure.gz"))) continue; } l.add(f); } return sortFilesByNameDesc(l); } static String stringIf(boolean b, String s) { return stringIfTrue(b, s); } static void clearConceptsOf(String progID) { getProgramFile(progID, "concepts.structure").delete(); getProgramFile(progID, "concepts.structure.gz").delete(); getProgramFile(progID, "idCounter.structure").delete(); } static Lock saveLock_lock = fairLock(); static Lock saveLock() { return saveLock_lock; } static String conceptsFileName() { return "concepts.structure.gz"; } static String dbProgramID() { return getDBProgramID(); } static List callF_all(Collection l, Object... args) { return map(l, f -> callF(f, args)); } static File tempFileFor(File f) { return new File(f.getPath() + "_temp"); } static double toM_double(long l) { return l / (1024 * 1024.0); } public static String rtrimSpaces(String s) { if (s == null) return null; int i = s.length(); while (i > 0 && " \t".indexOf(s.charAt(i - 1)) >= 0) --i; return i < s.length() ? s.substring(0, i) : s; } static int year() { return localYear(); } static int year(long now) { return localYear(now); } static int year(long now, TimeZone tz) { return parseInt(simpleDateFormat("y", tz).format(now)); } static int month() { return localMonth(); } static int month(long now) { return localMonth(now); } static int month(long now, TimeZone tz) { return parseInt(simpleDateFormat("M", tz).format(now)); } static int dayOfMonth() { return localDayOfMonth(); } static int dayOfMonth(long now) { return localDayOfMonth(now); } static int dayOfMonth(long now, TimeZone tz) { return parseInt(simpleDateFormat("d", tz).format(now)); } static java.util.Calendar calendarFromTime(long time, TimeZone tz) { java.util.Calendar c = java.util.Calendar.getInstance(tz); c.setTimeInMillis(time); return c; } static java.util.Calendar calendarFromTime(long time) { java.util.Calendar c = java.util.Calendar.getInstance(); c.setTimeInMillis(time); return c; } // r may return false to cancel timer static TimerTask smartTimerTask(Object r, java.util.Timer timer, long delay) { return new SmartTimerTask(r, timer, delay, _threadInfo()); } static class SmartTimerTask extends TimerTask implements IFieldsToList { Object r; java.util.Timer timer; long delay; Object threadInfo; SmartTimerTask() { } SmartTimerTask(Object r, java.util.Timer timer, long delay, Object threadInfo) { this.threadInfo = threadInfo; this.delay = delay; this.timer = timer; this.r = r; } public String toString() { return shortClassName(this) + "(" + r + ", " + timer + ", " + delay + ", " + threadInfo + ")"; } public Object[] _fieldsToList() { return new Object[] { r, timer, delay, threadInfo }; } long lastRun; public void run() { if (!licensed()) timer.cancel(); else { _threadInheritInfo(threadInfo); AutoCloseable __1 = tempActivity(r); try { lastRun = fixTimestamp(lastRun); long now = now(); if (now >= lastRun + delay * 0.9) { lastRun = now; if (eq(false, pcallF(r))) timer.cancel(); } } finally { _close(__1); } } } } static String dynamicClassName(Object o) { if (o instanceof DynamicObject && ((DynamicObject) o).className != null) return "main$" + ((DynamicObject) o).className; return className(o); } static List syncList() { return synchroList(); } static List syncList(List l) { return synchroList(l); } // o is either a map already (string->object) or an arbitrary object, // in which case its fields are converted into a map. static Map objectToMap(Object o) { try { if (o instanceof Map) return (Map) o; TreeMap map = new TreeMap(); Class c = o.getClass(); while (c != Object.class) { Field[] fields = c.getDeclaredFields(); for (final Field field : fields) { if ((field.getModifiers() & Modifier.STATIC) != 0) continue; field.setAccessible(true); final Object value = field.get(o); if (value != null) map.put(field.getName(), value); } c = c.getSuperclass(); } // XXX NEW - hopefully this doesn't break anything if (o instanceof DynamicObject) putAll(map, ((DynamicObject) o).fieldValues); return map; } catch (Exception __e) { throw rethrow(__e); } } // same for a collection (convert each element) static List> objectToMap(Iterable l) { if (l == null) return null; List x = new ArrayList(); for (Object o : l) x.add(objectToMap(o)); return x; } static Set allFields(Object o) { TreeSet fields = new TreeSet(); Class _c = _getClass(o); do { for (Field f : _c.getDeclaredFields()) fields.add(f.getName()); _c = _c.getSuperclass(); } while (_c != null); return fields; } static int stdHash(Object a, String... fields) { if (a == null) return 0; int hash = getClassName(a).hashCode(); for (String field : fields) hash = boostHashCombine(hash, hashCode(getOpt(a, field))); return hash; } static ListIterator emptyListIterator() { return Collections.emptyListIterator(); } static int latestInstalledJavaX() { File[] files = new File(userHome(), ".javax").listFiles(); int v = 0; if (files != null) for (File f : files) { Matcher m = regexpMatcher("x(\\d\\d\\d?)\\.jar", f.getName()); if (m.matches()) v = Math.max(v, Integer.parseInt(m.group(1))); } return v; } static String x30JarServerURL() { return "http://botcompany.de:8081/x30.jar"; } static boolean eitherIsA(Either e) { return e != null && e.isA(); } static double msToSeconds(long ms) { return toSeconds(ms); } static long fileModificationTime(File f) { return f == null ? 0 : f.lastModified(); } static void closeRandomAccessFile(RandomAccessFile f) { if (f != null) try { f.close(); callJavaX("dropIO", f); } catch (Throwable e) { printStackTrace(e); } } static RandomAccessFile newRandomAccessFile(File path, String mode) { try { boolean forWrite = mode.indexOf('w') >= 0; if (forWrite) mkdirsForFile(path); RandomAccessFile f = new RandomAccessFile(path, mode); callJavaX("registerIO", f, path, forWrite); return f; } catch (Exception __e) { throw rethrow(__e); } } static A vmBus_timerStarted(A timer) { vmBus_send("timerStarted", timer, costCenter()); return timer; } static String getBotAddress(String bot) { List l = fullBotScan(bot); return empty(l) ? null : first(l).address; } static Object unstructure_matchOK2OrFail(String s) { if (swic(s, "ok ")) return unstructure_startingAtIndex(s, 3); else throw fail(s); } static boolean isFile(File f) { return f != null && f.isFile(); } static boolean isFile(String path) { return isFile(newFile(path)); } static List sortFilesByName(List l) { sort(l, (a, b) -> stdcompare(a.getName(), b.getName())); return l; } static String regexpFirstGroup(String pat, String s) { Matcher m = regexpMatcher(pat, s); if (m.find()) return m.group(1); else return null; } static List sortFilesByNameDesc(List l) { sort(l, (a, b) -> stdcompare(b.getName(), a.getName())); return l; } static String stringIfTrue(boolean b, String s) { return b ? s : ""; } static int localYear() { return localYear(now()); } static int localYear(long time) { return parseInt(simpleDateFormat_local("yyyy").format(time)); } static java.text.SimpleDateFormat simpleDateFormat(String format, TimeZone timeZone) { java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat(format); sdf.setTimeZone(timeZone); return sdf; } static int localMonth(long time) { return parseInt(simpleDateFormat_local("MM").format(time)); } static int localMonth() { return localMonth(now()); } static int localDayOfMonth(long time) { return parseInt(simpleDateFormat_local("dd").format(time)); } static int localDayOfMonth() { return localDayOfMonth(now()); } static long fixTimestamp(long timestamp) { return timestamp > now() ? 0 : timestamp; } static int hashCode(Object a) { return a == null ? 0 : a.hashCode(); } static double toSeconds(long ms) { return ms / 1000.0; } static String toSeconds(long ms, int digits) { return formatDouble(toSeconds(ms), digits); } static double toSeconds(double ms) { return ms / 1000.0; } static String toSeconds(double ms, int digits) { return formatDouble(toSeconds(ms), digits); } static Object callJavaX(String method, Object... args) { return callOpt(getJavaX(), method, args); } static Object costCenter() { return mc(); } static class ScannedBot implements IFieldsToList { static final String _fieldOrder = "helloString address"; String helloString; String address; ScannedBot() { } ScannedBot(String helloString, String address) { this.address = address; this.helloString = helloString; } public String toString() { return shortClassName(this) + "(" + helloString + ", " + address + ")"; } public boolean equals(Object o) { if (!(o instanceof ScannedBot)) return false; ScannedBot __1 = (ScannedBot) o; return eq(helloString, __1.helloString) && eq(address, __1.address); } public int hashCode() { int h = 1660478935; h = boostHashCombine(h, _hashCode(helloString)); h = boostHashCombine(h, _hashCode(address)); return h; } public Object[] _fieldsToList() { return new Object[] { helloString, address }; } } static List fullBotScan() { return fullBotScan(""); } static List fullBotScan(String searchPattern) { List bots = new ArrayList(); for (ProgramScan.Program p : quickBotScan()) { String botName = firstPartOfHelloString(p.helloString); boolean isVM = startsWithIgnoreCase(p.helloString, "This is a JavaX VM."); boolean shouldRecurse = swic(botName, "Multi-Port") || isVM; if (swic(botName, searchPattern)) bots.add(new ScannedBot(botName, "" + p.port)); if (shouldRecurse) try { Map subBots = (Map) unstructure(sendToLocalBotQuietly(p.port, "list bots")); for (Number vport : subBots.keySet()) { botName = subBots.get(vport); if (swic(botName, searchPattern)) bots.add(new ScannedBot(botName, p.port + "/" + vport)); } } catch (Exception e) { e.printStackTrace(); } } return bots; } static Object unstructure_startingAtIndex(String s, int i) { return unstructure_tok(javaTokC_noMLS_iterator(s, i), false, null); } static class Str extends Concept { String name; List otherNames = new ArrayList(); Str() { } Str(String name) { this.name = name; } public String toString() { return name; } } static class CountingOutputStream extends FilterOutputStream { long counter; CountingOutputStream(OutputStream out) { super(out); } @Override public void write(int b) throws IOException { ++counter; out.write(b); } @Override public void write(byte[] b) throws IOException { counter += b.length; out.write(b, 0, b.length); } @Override public void write(byte[] b, int off, int len) throws IOException { if (len == 0) return; counter += len; out.write(b, off, len); } long getFilePointer() { return counter; } } static class Scored extends Var { float score; Scored() { } Scored(A a, float score) { super(a); this.score = score; } Scored(A a, double score) { super(a); this.score = (float) score; } float score() { return score; } public String toString() { return toIntPercent(score) + "%: " + str(get()); } } static class FixedRateTimer extends java.util.Timer { FixedRateTimer() { this(false); } FixedRateTimer(boolean daemon) { this(defaultTimerName(), daemon); } FixedRateTimer(String name) { this(name, false); } FixedRateTimer(String name, boolean daemon) { super(name, daemon); _registerTimer(this); } List entries = synchroList(); static class Entry implements IFieldsToList { TimerTask task; long firstTime; long period; Entry() { } Entry(TimerTask task, long firstTime, long period) { this.period = period; this.firstTime = firstTime; this.task = task; } public String toString() { return shortClassName(this) + "(" + task + ", " + firstTime + ", " + period + ")"; } public Object[] _fieldsToList() { return new Object[] { task, firstTime, period }; } } // Note: not all methods overridden; only use these ones public void scheduleAtFixedRate(TimerTask task, long delay, long period) { entries.add(new Entry(task, now() + delay, period)); super.scheduleAtFixedRate(task, delay, period); } public void cancel() { entries.clear(); super.cancel(); } public int purge() { entries.clear(); return super.purge(); } FixedRateTimer changeRate(int newPeriod) { Object r = ((SmartTimerTask) first(entries).task).r; cancel(); return doEvery(newPeriod, r); } } static int toIntPercent(double ratio) { return roundToInt(ratio * 100); } // when used with map function static int toIntPercent(float ratio) { return toIntPercent((double) ratio); } static String defaultTimerName_name; static String defaultTimerName() { if (defaultTimerName_name == null) defaultTimerName_name = "A timer by " + programID(); return defaultTimerName_name; } static Set _registerTimer_list = newWeakHashSet(); static void _registerTimer(java.util.Timer timer) { _registerTimer_list.add(timer); } static void cleanMeUp__registerTimer() { cancelTimers(getAndClearList(_registerTimer_list)); } static int roundToInt(double d) { return (int) Math.round(d); } static void cancelTimers(Collection timers) { for (Object timer : timers) cancelTimer(timer); } static List getAndClearList(Collection l) { if (l == null) return emptyList(); synchronized (collectionMutex(l)) { List out = cloneList(l); l.clear(); return out; } } }