diff --git a/Arduino/BROBOT_EVO2/BROBOT_EVO2.ino b/Arduino/BROBOT_EVO2/BROBOT_EVO2.ino index ed9beed..bf3a870 100644 --- a/Arduino/BROBOT_EVO2/BROBOT_EVO2.ino +++ b/Arduino/BROBOT_EVO2/BROBOT_EVO2.ino @@ -1,23 +1,23 @@ // BROBOT EVO 2 by JJROBOTS -// SELF BALANCE ARDUINO ROBOT WITH STEPPER MOTORS +// SELF BALANCE ARDUINO ROBOT WITH STEPPER MOTORS CONTROLLED WITH YOUR SMARTPHONE // JJROBOTS BROBOT KIT: (Arduino Leonardo + BROBOT ELECTRONIC BRAIN SHIELD + STEPPER MOTOR drivers) // This code is prepared for new BROBOT shield with ESP8266 Wifi module -// This code doesn´t need external libraries // Author: JJROBOTS.COM // Date: 02/09/2014 -// Updated: 06/05/2017 -// Version: 2.81 +// Updated: 25/06/2017 +// Version: 2.82 // License: GPL v2 -// Project URL: http://jjrobots.com/b-robot (Features,documentation,build instructions,how it works, SHOP,...) +// Compiled and tested with Arduino 1.6.8. This new version of code does not need external libraries (only Arduino standard libraries) +// Project URL: http://jjrobots.com/b-robot-evo-2-much-more-than-a-self-balancing-robot (Features,documentation,build instructions,how it works, SHOP,...) // New updates: -// - New default parameters specially tuned for BROBOT EVO 2 version -// - New Move mode with position control (for externally programming the robot) +// - New default parameters specially tuned for BROBOT EVO 2 version (More agile, more stable...) +// - New Move mode with position control (for externally programming the robot with a Blockly or pyhton programming interfaces) // - New telemtry packets send to TELEMETRY IP for monitoring Battery, Angle, ... (old battery packets for touch osc not working now) // - Default telemetry server is 192.168.4.2 (first client connected to the robot) // Get the free android app (jjrobots) from google play. For IOS users you need to use TouchOSC App + special template (info on jjrobots page) // Thanks to our users on the forum for the new ideas. Specially sasa999, KomX, ... -// The board needs at least 10-15 seconds with no motion (robot steady) at beginning to give good values... +// The board needs at least 10-15 seconds with no motion (robot steady) at beginning to give good values... Robot move slightly when it´s ready! // MPU6050 IMU connected via I2C bus. Angle estimation using complementary filter (fusion between gyro and accel) // Angle calculations and control part is running at 100Hz @@ -61,14 +61,14 @@ #define MAX_TARGET_ANGLE 14 // PRO MODE = MORE AGGRESSIVE (MAXIMUN SETTINGS) -#define MAX_THROTTLE_PRO 860 -#define MAX_STEERING_PRO 280 -#define MAX_TARGET_ANGLE_PRO 32 +#define MAX_THROTTLE_PRO 780 // Max recommended value: 860 +#define MAX_STEERING_PRO 260 // Max recommended value: 280 +#define MAX_TARGET_ANGLE_PRO 26 // Max recommended value: 32 // Default control terms for EVO 2 #define KP 0.32 #define KD 0.050 -#define KP_THROTTLE 0.075 +#define KP_THROTTLE 0.080 #define KI_THROTTLE 0.1 #define KP_POSITION 0.06 #define KD_POSITION 0.45 @@ -84,20 +84,23 @@ #define ITERM_MAX_ERROR 30 // Iterm windup constants for PI control #define ITERM_MAX 10000 -#define ANGLE_OFFSET -1.0 // Offset angle for balance (to compensate robot own weitght distribution) +#define ANGLE_OFFSET 0.0 // Offset angle for balance (to compensate robot own weight distribution) // Servo definitions #define SERVO_AUX_NEUTRO 1500 // Servo neutral position #define SERVO_MIN_PULSEWIDTH 700 #define SERVO_MAX_PULSEWIDTH 2500 +#define SERVO2_NEUTRO 1500 +#define SERVO2_RANGE 1400 + // Telemetry #define TELEMETRY_BATTERY 1 #define TELEMETRY_ANGLE 1 //#define TELEMETRY_DEBUG 1 // Dont use TELEMETRY_ANGLE and TELEMETRY_DEBUG at the same time! #define ZERO_SPEED 65535 -#define MAX_ACCEL 15 // Maximun motor acceleration (MAX RECOMMENDED VALUE: 20) (default:15) +#define MAX_ACCEL 14 // Maximun motor acceleration (MAX RECOMMENDED VALUE: 20) (default:14) #define MICROSTEPPING 16 // 8 or 16 for 1/8 or 1/16 driver microstepping (default:16) @@ -125,6 +128,7 @@ float dt; // Angle of the robot (used for stability control) float angle_adjusted; float angle_adjusted_Old; +float angle_adjusted_filtered=0.0; // Default control values from constant definitions float Kp = KP; @@ -152,6 +156,7 @@ float max_throttle = MAX_THROTTLE; float max_steering = MAX_STEERING; float max_target_angle = MAX_TARGET_ANGLE; float control_output; +float angle_offset = ANGLE_OFFSET; boolean positionControlMode = false; uint8_t mode; // mode = 0 Normal mode, mode = 1 Pro mode (More agressive) @@ -311,20 +316,23 @@ void setup() setMotorSpeedM1(5); setMotorSpeedM2(5); BROBOT_moveServo1(SERVO_AUX_NEUTRO + 100); + BROBOT_moveServo2(SERVO2_NEUTRO + 100); delay(200); setMotorSpeedM1(-5); setMotorSpeedM2(-5); BROBOT_moveServo1(SERVO_AUX_NEUTRO - 100); + BROBOT_moveServo2(SERVO2_NEUTRO - 100); delay(200); } BROBOT_moveServo1(SERVO_AUX_NEUTRO); + BROBOT_moveServo2(SERVO2_NEUTRO); #if TELEMETRY_BATTERY==1 BatteryValue = BROBOT_readBattery(true); Serial.print("BATT:"); Serial.println(BatteryValue); #endif - Serial.println("BROBOT by JJROBOTS v2.81"); + Serial.println("BROBOT by JJROBOTS v2.82"); Serial.println("Start..."); timer_old = micros(); } @@ -414,12 +422,19 @@ void loop() angle_adjusted_Old = angle_adjusted; // Get new orientation angle from IMU (MPU6050) - angle_adjusted = MPU6050_getAngle(dt) + ANGLE_OFFSET; - + float MPU_sensor_angle = MPU6050_getAngle(dt); + angle_adjusted = MPU_sensor_angle + angle_offset; + if ((MPU_sensor_angle>-15)&&(MPU_sensor_angle<15)) + angle_adjusted_filtered = angle_adjusted_filtered*0.99 + MPU_sensor_angle*0.01; + #if DEBUG==1 Serial.print(dt); Serial.print(" "); - Serial.println(angle_adjusted); + Serial.print(angle_offset); + Serial.print(" "); + Serial.print(angle_adjusted); + Serial.print(","); + Serial.println(angle_adjusted_filtered); #endif //Serial.print("\t"); @@ -480,7 +495,7 @@ void loop() int angle_ready; if (OSCpush[0]) // If we press the SERVO button we start to move - angle_ready = 80; + angle_ready = 82; else angle_ready = 74; // Default angle if ((angle_adjusted < angle_ready) && (angle_adjusted > -angle_ready)) // Is robot ready (upright?) @@ -504,6 +519,10 @@ void loop() // RESET steps steps1 = 0; steps2 = 0; + positionControlMode = false; + OSCmove_mode = false; + throttle = 0; + steering = 0; } // Push1 Move servo arm @@ -517,6 +536,9 @@ void loop() else BROBOT_moveServo1(SERVO_AUX_NEUTRO); + // Servo2 + BROBOT_moveServo2(SERVO2_NEUTRO + (OSCfader[2] - 0.5) * SERVO2_RANGE); + // Normal condition? if ((angle_adjusted < 56) && (angle_adjusted > -56)) { diff --git a/Arduino/BROBOT_EVO2/Network.ino b/Arduino/BROBOT_EVO2/Network.ino index 7af4c32..37639ed 100644 --- a/Arduino/BROBOT_EVO2/Network.ino +++ b/Arduino/BROBOT_EVO2/Network.ino @@ -39,6 +39,14 @@ void readControlParameters() Serial.println(Ki_thr_user); #endif + // Calibration mode?? + if (OSCpush[2]==1) + { + Serial.print("Calibration MODE "); + angle_offset = angle_adjusted_filtered; + Serial.println(angle_offset); + } + // Kill robot => Sleep while (OSCtoggle[0] == 1) { diff --git a/Arduino/BROBOT_EVO2/OSC.ino b/Arduino/BROBOT_EVO2/OSC.ino index acf737c..0f75fae 100644 --- a/Arduino/BROBOT_EVO2/OSC.ino +++ b/Arduino/BROBOT_EVO2/OSC.ino @@ -98,8 +98,6 @@ void OSC_MsgRead() // New bytes available to process? if (Serial1.available() > 0) { - //Serial.print("B:"); - //Serial.println(Serial1_available()); // We rotate the Buffer (we could implement a ring buffer in future) for (i = 7; i > 0; i--) { UDPBuffer[i] = UDPBuffer[i - 1]; @@ -211,7 +209,7 @@ void OSC_MsgRead() } #ifdef OSCDEBUG Serial.print("$F1:"); - Serial.println(OSCfadder[0]); + Serial.println(OSCfader[0]); #endif break; case 2: @@ -224,21 +222,21 @@ void OSC_MsgRead() } #ifdef OSCDEBUG Serial.print("$F2:"); - Serial.println(OSCfadder[1]); + Serial.println(OSCfader[1]); #endif break; case 3: OSCfader[2] = OSC_extractParamFloat(0); #ifdef OSCDEBUG Serial.print("$F3:"); - Serial.println(OSCfadder[2]); + Serial.println(OSCfader[2]); #endif break; case 4: OSCfader[3] = OSC_extractParamFloat(0); #ifdef OSCDEBUG Serial.print("$F4:"); - Serial.println(OSCfadder[3]); + Serial.println(OSCfader[3]); #endif break; case 11: diff --git a/Arduino/BROBOT_EVO2/Servos.ino b/Arduino/BROBOT_EVO2/Servos.ino index a12a145..1ce8a1f 100644 --- a/Arduino/BROBOT_EVO2/Servos.ino +++ b/Arduino/BROBOT_EVO2/Servos.ino @@ -70,8 +70,8 @@ void BROBOT_moveServo2(int pwm) pwm = constrain(pwm,SERVO2_MIN_PULSEWIDTH,SERVO2_MAX_PULSEWIDTH)>>3; // Check max values and Resolution: 8us // 11 bits => 3 MSB bits on TC4H, LSB bits on OCR4B TC4H = pwm>>8; - OCR4A = pwm & 0xFF; // Old 2.0 boards servo2 output - OCR4D = pwm & 0xFF; // New 2.1 boards servo2 output + OCR4A = pwm & 0xFF; // 2.0 or 2.3 boards servo2 output + OCR4D = pwm & 0xFF; // 2.1 or 2.4 boards servo2 output } // output : Battery voltage*10 (aprox) and noise filtered diff --git a/Blockly/BROBOT_Blockly.exe b/Blockly/BROBOT_Blockly.exe new file mode 100644 index 0000000..115167d Binary files /dev/null and b/Blockly/BROBOT_Blockly.exe differ diff --git a/Blockly/CRYPT32.dll b/Blockly/CRYPT32.dll new file mode 100644 index 0000000..88609b4 Binary files /dev/null and b/Blockly/CRYPT32.dll differ diff --git a/Blockly/_hashlib.pyd b/Blockly/_hashlib.pyd new file mode 100644 index 0000000..9673825 Binary files /dev/null and b/Blockly/_hashlib.pyd differ diff --git a/Blockly/_socket.pyd b/Blockly/_socket.pyd new file mode 100644 index 0000000..5487198 Binary files /dev/null and b/Blockly/_socket.pyd differ diff --git a/Blockly/_ssl.pyd b/Blockly/_ssl.pyd new file mode 100644 index 0000000..ff6216c Binary files /dev/null and b/Blockly/_ssl.pyd differ diff --git a/Blockly/brobot/Brobot2.jpg b/Blockly/brobot/Brobot2.jpg new file mode 100644 index 0000000..d515044 Binary files /dev/null and b/Blockly/brobot/Brobot2.jpg differ diff --git a/Blockly/brobot/Brobot2_old.jpg b/Blockly/brobot/Brobot2_old.jpg new file mode 100644 index 0000000..b790f6f Binary files /dev/null and b/Blockly/brobot/Brobot2_old.jpg differ diff --git a/Blockly/brobot/LICENSE b/Blockly/brobot/LICENSE new file mode 100644 index 0000000..6a19929 --- /dev/null +++ b/Blockly/brobot/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2011 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/Blockly/brobot/README.md b/Blockly/brobot/README.md new file mode 100644 index 0000000..fd626a4 --- /dev/null +++ b/Blockly/brobot/README.md @@ -0,0 +1,8 @@ +# Blockly + +Google's Blockly is a web-based, visual programming editor. Users can drag +blocks together to build programs. All code is free and open source. + +**The project page is https://developers.google.com/blockly/** + +![](https://developers.google.com/blockly/images/sample.png) diff --git a/Blockly/brobot/blockly_compressed.js b/Blockly/brobot/blockly_compressed.js new file mode 100644 index 0000000..dd378c0 --- /dev/null +++ b/Blockly/brobot/blockly_compressed.js @@ -0,0 +1,1467 @@ +// Do not edit this file; automatically generated by build.py. +'use strict'; + +var COMPILED=!0,goog=goog||{};goog.global=this;goog.isDef=function(a){return void 0!==a};goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&goog.isDef(b)?c[d]=b:c=c[d]?c[d]:c[d]={}}; +goog.define=function(a,b){var c=b;COMPILED||(goog.global.CLOSURE_UNCOMPILED_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_UNCOMPILED_DEFINES,a)?c=goog.global.CLOSURE_UNCOMPILED_DEFINES[a]:goog.global.CLOSURE_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES,a)&&(c=goog.global.CLOSURE_DEFINES[a]));goog.exportPath_(a,c)};goog.DEBUG=!1;goog.LOCALE="en";goog.TRUSTED_SITE=!0;goog.STRICT_MODE_COMPATIBLE=!1;goog.DISALLOW_TEST_ONLY_CODE=COMPILED&&!goog.DEBUG; +goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING=!1;goog.provide=function(a){if(goog.isInModuleLoader_())throw Error("goog.provide can not be used within a goog.module.");if(!COMPILED&&goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');goog.constructNamespace_(a)};goog.constructNamespace_=function(a,b){if(!COMPILED){delete goog.implicitNamespaces_[a];for(var c=a;(c=c.substring(0,c.lastIndexOf(".")))&&!goog.getObjectByName(c);)goog.implicitNamespaces_[c]=!0}goog.exportPath_(a,b)}; +goog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/;goog.module=function(a){if(!goog.isString(a)||!a||-1==a.search(goog.VALID_MODULE_RE_))throw Error("Invalid module identifier");if(!goog.isInModuleLoader_())throw Error("Module "+a+" has been loaded incorrectly.");if(goog.moduleLoaderState_.moduleName)throw Error("goog.module may only be called once per module.");goog.moduleLoaderState_.moduleName=a;if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');delete goog.implicitNamespaces_[a]}}; +goog.module.get=function(a){return goog.module.getInternal_(a)};goog.module.getInternal_=function(a){if(!COMPILED)return goog.isProvided_(a)?a in goog.loadedModules_?goog.loadedModules_[a]:goog.getObjectByName(a):null};goog.moduleLoaderState_=null;goog.isInModuleLoader_=function(){return null!=goog.moduleLoaderState_}; +goog.module.declareLegacyNamespace=function(){if(!COMPILED&&!goog.isInModuleLoader_())throw Error("goog.module.declareLegacyNamespace must be called from within a goog.module");if(!COMPILED&&!goog.moduleLoaderState_.moduleName)throw Error("goog.module must be called prior to goog.module.declareLegacyNamespace.");goog.moduleLoaderState_.declareLegacyNamespace=!0}; +goog.setTestOnly=function(a){if(goog.DISALLOW_TEST_ONLY_CODE)throw a=a||"",Error("Importing test-only code into non-debug environment"+(a?": "+a:"."));};goog.forwardDeclare=function(a){};COMPILED||(goog.isProvided_=function(a){return a in goog.loadedModules_||!goog.implicitNamespaces_[a]&&goog.isDefAndNotNull(goog.getObjectByName(a))},goog.implicitNamespaces_={"goog.module":!0}); +goog.getObjectByName=function(a,b){for(var c=a.split("."),d=b||goog.global,e;e=c.shift();)if(goog.isDefAndNotNull(d[e]))d=d[e];else return null;return d};goog.globalize=function(a,b){var c=b||goog.global,d;for(d in a)c[d]=a[d]}; +goog.addDependency=function(a,b,c,d){if(goog.DEPENDENCIES_ENABLED){var e;a=a.replace(/\\/g,"/");var f=goog.dependencies_;d&&"boolean"!==typeof d||(d=d?{module:"goog"}:{});for(var g=0;e=b[g];g++)f.nameToPath[e]=a,f.loadFlags[a]=d;for(d=0;b=c[d];d++)a in f.requires||(f.requires[a]={}),f.requires[a][b]=!0}};goog.ENABLE_DEBUG_LOADER=!0;goog.logToConsole_=function(a){goog.global.console&&goog.global.console.error(a)}; +goog.require=function(a){if(!COMPILED){goog.ENABLE_DEBUG_LOADER&&goog.IS_OLD_IE_&&goog.maybeProcessDeferredDep_(a);if(goog.isProvided_(a)){if(goog.isInModuleLoader_())return goog.module.getInternal_(a)}else if(goog.ENABLE_DEBUG_LOADER){var b=goog.getPathFromDeps_(a);if(b)goog.writeScripts_(b);else throw a="goog.require could not find: "+a,goog.logToConsole_(a),Error(a);}return null}};goog.basePath="";goog.nullFunction=function(){}; +goog.abstractMethod=function(){throw Error("unimplemented abstract method");};goog.addSingletonGetter=function(a){a.getInstance=function(){if(a.instance_)return a.instance_;goog.DEBUG&&(goog.instantiatedSingletons_[goog.instantiatedSingletons_.length]=a);return a.instance_=new a}};goog.instantiatedSingletons_=[];goog.LOAD_MODULE_USING_EVAL=!0;goog.SEAL_MODULE_EXPORTS=goog.DEBUG;goog.loadedModules_={};goog.DEPENDENCIES_ENABLED=!COMPILED&&goog.ENABLE_DEBUG_LOADER;goog.TRANSPILE="detect"; +goog.TRANSPILER="transpile.js"; +goog.DEPENDENCIES_ENABLED&&(goog.dependencies_={loadFlags:{},nameToPath:{},requires:{},visited:{},written:{},deferred:{}},goog.inHtmlDocument_=function(){var a=goog.global.document;return null!=a&&"write"in a},goog.findBasePath_=function(){if(goog.isDef(goog.global.CLOSURE_BASE_PATH))goog.basePath=goog.global.CLOSURE_BASE_PATH;else if(goog.inHtmlDocument_())for(var a=goog.global.document.getElementsByTagName("SCRIPT"),b=a.length-1;0<=b;--b){var c=a[b].src,d=c.lastIndexOf("?"),d=-1==d?c.length:d;if("base.js"== +c.substr(d-7,7)){goog.basePath=c.substr(0,d-7);break}}},goog.importScript_=function(a,b){(goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_)(a,b)&&(goog.dependencies_.written[a]=!0)},goog.IS_OLD_IE_=!(goog.global.atob||!goog.global.document||!goog.global.document.all),goog.importProcessedScript_=function(a,b,c){goog.importScript_("",'goog.retrieveAndExec_("'+a+'", '+b+", "+c+");")},goog.queuedModules_=[],goog.wrapModule_=function(a,b){return goog.LOAD_MODULE_USING_EVAL&&goog.isDef(goog.global.JSON)? +"goog.loadModule("+goog.global.JSON.stringify(b+"\n//# sourceURL="+a+"\n")+");":'goog.loadModule(function(exports) {"use strict";'+b+"\n;return exports});\n//# sourceURL="+a+"\n"},goog.loadQueuedModules_=function(){var a=goog.queuedModules_.length;if(0\x3c/script>')},goog.appendScriptSrcNode_=function(a){var b=goog.global.document,c=b.createElement("script");c.type="text/javascript";c.src=a;c.defer=!1;c.async=!1;b.head.appendChild(c)},goog.writeScriptTag_=function(a,b){if(goog.inHtmlDocument_()){var c= +goog.global.document;if(!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING&&"complete"==c.readyState){if(/\bdeps.js$/.test(a))return!1;throw Error('Cannot write "'+a+'" after document load');}if(void 0===b)if(goog.IS_OLD_IE_){var d=" onreadystatechange='goog.onScriptLoad_(this, "+ ++goog.lastNonModuleScriptIndex_+")' ";c.write(' + var link = document.createElement('link'); + link.setAttribute('rel', 'stylesheet'); + link.setAttribute('href', 'demos/prettify.css'); + document.head.appendChild(link); + var script = document.createElement('script'); + script.setAttribute('src', 'demos/prettify.js'); + document.head.appendChild(script); +}; + +/** + * Compute the absolute coordinates and dimensions of an HTML element. + * @param {!Element} element Element to match. + * @return {!Object} Contains height, width, x, and y properties. + * @private + */ +Code.getBBox_ = function(element) { + var height = element.offsetHeight; + var width = element.offsetWidth; + var x = 0; + var y = 0; + do { + x += element.offsetLeft; + y += element.offsetTop; + element = element.offsetParent; + } while (element); + return { + height: height, + width: width, + x: x, + y: y + }; +}; + +/** + * User's language (e.g. "en"). + * @type {string} + */ +Code.LANG = Code.getLang(); + +/** + * List of tab names. + * @private + */ +Code.TABS_ = ['blocks', 'javascript', 'python', 'xml']; +Code.selected = 'blocks'; + +/** + * Switch the visible pane when a tab is clicked. + * @param {string} clickedName Name of tab clicked. + */ +Code.tabClick = function(clickedName) { + // If the XML tab was open, save and render the content. + if (document.getElementById('tab_xml').className == 'tabon') { + var xmlTextarea = document.getElementById('content_xml'); + var xmlText = xmlTextarea.value; + var xmlDom = null; + try { + xmlDom = Blockly.Xml.textToDom(xmlText); + } catch (e) { + var q = + window.confirm(MSG['badXml'].replace('%1', e)); + if (!q) { + // Leave the user on the XML tab. + return; + } + } + if (xmlDom) { + Code.workspace.clear(); + Blockly.Xml.domToWorkspace(xmlDom, Code.workspace); + } + } + + if (document.getElementById('tab_blocks').className == 'tabon') { + Code.workspace.setVisible(false); + } + // Deselect all tabs and hide all panes. + for (var i = 0; i < Code.TABS_.length; i++) { + var name = Code.TABS_[i]; + document.getElementById('tab_' + name).className = 'taboff'; + document.getElementById('content_' + name).style.visibility = 'hidden'; + } + + // Select the active tab. + Code.selected = clickedName; + document.getElementById('tab_' + clickedName).className = 'tabon'; + // Show the selected pane. + document.getElementById('content_' + clickedName).style.visibility = + 'visible'; + Code.renderContent(); + if (clickedName == 'blocks') { + Code.workspace.setVisible(true); + } + Blockly.svgResize(Code.workspace); +}; + +/** + * Populate the currently selected pane with content generated from the blocks. + */ +Code.renderContent = function() { + var content = document.getElementById('content_' + Code.selected); + // Initialize the pane. + if (content.id == 'content_xml') { + var xmlTextarea = document.getElementById('content_xml'); + var xmlDom = Blockly.Xml.workspaceToDom(Code.workspace); + var xmlText = Blockly.Xml.domToPrettyText(xmlDom); + xmlTextarea.value = xmlText; + xmlTextarea.focus(); + } else if (content.id == 'content_javascript') { + var code = "// BROBOT code\n"; + code += "var STEPSMETER="+STEPSMETER+";\nvar STEPSTURN="+STEPSTURN+";\n\n"; + code += Blockly.JavaScript.workspaceToCode(Code.workspace); + content.textContent = code; + if (typeof prettyPrintOne == 'function') { + code = content.innerHTML; + code = prettyPrintOne(code, 'js'); + content.innerHTML = code; + } + } else if (content.id == 'content_python') { + // Add python Initialization code + code = '# PYTHON BROBOT CODE\n'; + code +='import time\nfrom BROBOT_Class import BROBOT\n'; + code += 'myRobot = BROBOT()\n\n'; + code += Blockly.Python.workspaceToCode(Code.workspace); + content.textContent = code; + if (typeof prettyPrintOne == 'function') { + code = content.innerHTML; + code = prettyPrintOne(code, 'py'); + content.innerHTML = code; + } + + } +}; + +/** + * Initialize Blockly. Called on page load. + */ +Code.init = function() { + $( function() { + $( "#dialog" ).dialog(); + } ); + Code.initLanguage(); + + var container = document.getElementById('content_area'); + var onresize = function(e) { + var bBox = Code.getBBox_(container); + for (var i = 0; i < Code.TABS_.length; i++) { + var el = document.getElementById('content_' + Code.TABS_[i]); + el.style.top = bBox.y + 'px'; + el.style.left = bBox.x + 'px'; + // Height and width need to be set, read back, then set again to + // compensate for scrollbars. + el.style.height = bBox.height + 'px'; + el.style.height = (2 * bBox.height - el.offsetHeight) + 'px'; + el.style.width = bBox.width + 'px'; + el.style.width = (2 * bBox.width - el.offsetWidth) + 'px'; + } + // Make the 'Blocks' tab line up with the toolbox. + if (Code.workspace && Code.workspace.toolbox_.width) { + document.getElementById('tab_blocks').style.minWidth = + (Code.workspace.toolbox_.width - 38) + 'px'; + // Account for the 19 pixel margin and on each side. + } + }; + window.addEventListener('resize', onresize, false); + + // Interpolate translated messages into toolbox. + var toolboxText = document.getElementById('toolbox').outerHTML; + toolboxText = toolboxText.replace(/{(\w+)}/g, + function(m, p1) {return MSG[p1]}); + var toolboxXml = Blockly.Xml.textToDom(toolboxText); + + Code.workspace = Blockly.inject('content_blocks', + {grid: + {spacing: 25, + length: 3, + colour: '#ccc', + snap: true}, + media: 'media/', + toolbox: toolboxXml, + zoom: + {controls: true, + wheel: true} + }); + + // Add to reserved word list: Local variables in execution environment (runJS) + // and the infinite loop detection function. + // Blockly.JavaScript.addReservedWords('code,timeouts,checkTimeout'); + + Code.loadBlocks(''); + + if ('BlocklyStorage' in window) { + // Hook a save function onto unload. + BlocklyStorage.backupOnUnload(Code.workspace); + } + + Code.tabClick(Code.selected); + + Code.bindClick('trashButton', + function() {Code.discard(); Code.renderContent();}); + Code.bindClick('runButton', Code.runJS); + // Disable the link button if page isn't backed by App Engine storage. + var linkButton = document.getElementById('linkButton'); + if ('BlocklyStorage' in window) { + BlocklyStorage['HTTPREQUEST_ERROR'] = MSG['httpRequestError']; + BlocklyStorage['LINK_ALERT'] = MSG['linkAlert']; + BlocklyStorage['HASH_ERROR'] = MSG['hashError']; + BlocklyStorage['XML_ERROR'] = MSG['xmlError']; + Code.bindClick(linkButton, + function() {BlocklyStorage.link(Code.workspace);}); + } else if (linkButton) { + linkButton.className = 'disabled'; + } + + for (var i = 0; i < Code.TABS_.length; i++) { + var name = Code.TABS_[i]; + Code.bindClick('tab_' + name, + function(name_) {return function() {Code.tabClick(name_);};}(name)); + } + onresize(); + Blockly.svgResize(Code.workspace); + + // Lazy-load the syntax-highlighting. + window.setTimeout(Code.importPrettify, 1); +}; + +/** + * Initialize the page language. + */ +Code.initLanguage = function() { + document.head.parentElement.setAttribute('lang', 'en'); + + // Inject language strings. + document.title += ' ' + 'title'; + document.getElementById('tab_blocks').textContent = 'blocks'; + document.getElementById('linkButton').title = 'link'; + document.getElementById('runButton').title = 'run'; + document.getElementById('trashButton').title = 'trash'; +}; + +/** + * Execute the user's code. + * Just a quick and dirty eval. Catch infinite loops. + */ +Code.runJS = function() { + console.log('run code...'); + Blockly.JavaScript.INFINITE_LOOP_TRAP = ' checkTimeout();\n'; + var timeouts = 0; + var checkTimeout = function() { + if (timeouts++ > 1000000) { + throw MSG['timeout']; + } + }; + var code = Blockly.JavaScript.workspaceToCode(Code.workspace); + Blockly.JavaScript.INFINITE_LOOP_TRAP = null; + console.log(code); + eval(code); + + //try { + // eval(code); + //} catch (e) { + // console.log('Code error...'); + //alert(MSG['badCode'].replace('%1', e)); + //} +}; + +/** + * Discard all blocks from the workspace. + */ +Code.discard = function() { + var count = Code.workspace.getAllBlocks().length; + if (count < 2 || + window.confirm(Blockly.Msg.DELETE_ALL_BLOCKS.replace('%1', count))) { + Code.workspace.clear(); + if (window.location.hash) { + window.location.hash = ''; + } + } +}; + +window.addEventListener('load', Code.init); diff --git a/Blockly/brobot/demos/prettify.css b/Blockly/brobot/demos/prettify.css new file mode 100644 index 0000000..d44b3a2 --- /dev/null +++ b/Blockly/brobot/demos/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} \ No newline at end of file diff --git a/Blockly/brobot/demos/prettify.js b/Blockly/brobot/demos/prettify.js new file mode 100644 index 0000000..7b99049 --- /dev/null +++ b/Blockly/brobot/demos/prettify.js @@ -0,0 +1,30 @@ +!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a= +b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;ah[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com", +/^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+ +s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/, +q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d= +c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], +O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, +V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", +/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], +["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}), +["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q, +hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]); +p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="
"+a+"
";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1}); +return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i> >>> +Blockly.JavaScript.ORDER_RELATIONAL = 8; // < <= > >= +Blockly.JavaScript.ORDER_IN = 8; // in +Blockly.JavaScript.ORDER_INSTANCEOF = 8; // instanceof +Blockly.JavaScript.ORDER_EQUALITY = 9; // == != === !== +Blockly.JavaScript.ORDER_BITWISE_AND = 10; // & +Blockly.JavaScript.ORDER_BITWISE_XOR = 11; // ^ +Blockly.JavaScript.ORDER_BITWISE_OR = 12; // | +Blockly.JavaScript.ORDER_LOGICAL_AND = 13; // && +Blockly.JavaScript.ORDER_LOGICAL_OR = 14; // || +Blockly.JavaScript.ORDER_CONDITIONAL = 15; // ?: +Blockly.JavaScript.ORDER_ASSIGNMENT = 16; // = += -= *= /= %= <<= >>= ... +Blockly.JavaScript.ORDER_COMMA = 17; // , +Blockly.JavaScript.ORDER_NONE = 99; // (...) + +/** + * List of outer-inner pairings that do NOT require parentheses. + * @type {!Array.>} + */ +Blockly.JavaScript.ORDER_OVERRIDES = [ + // (foo()).bar -> foo().bar + // (foo())[0] -> foo()[0] + [Blockly.JavaScript.ORDER_FUNCTION_CALL, Blockly.JavaScript.ORDER_MEMBER], + // (foo())() -> foo()() + [Blockly.JavaScript.ORDER_FUNCTION_CALL, Blockly.JavaScript.ORDER_FUNCTION_CALL], + // (foo.bar).baz -> foo.bar.baz + // (foo.bar)[0] -> foo.bar[0] + // (foo[0]).bar -> foo[0].bar + // (foo[0])[1] -> foo[0][1] + [Blockly.JavaScript.ORDER_MEMBER, Blockly.JavaScript.ORDER_MEMBER], + // (foo.bar)() -> foo.bar() + // (foo[0])() -> foo[0]() + [Blockly.JavaScript.ORDER_MEMBER, Blockly.JavaScript.ORDER_FUNCTION_CALL], + + // !(!foo) -> !!foo + [Blockly.JavaScript.ORDER_LOGICAL_NOT, Blockly.JavaScript.ORDER_LOGICAL_NOT], + // a * (b * c) -> a * b * c + [Blockly.JavaScript.ORDER_MULTIPLICATION, Blockly.JavaScript.ORDER_MULTIPLICATION], + // a + (b + c) -> a + b + c + [Blockly.JavaScript.ORDER_ADDITION, Blockly.JavaScript.ORDER_ADDITION], + // a && (b && c) -> a && b && c + [Blockly.JavaScript.ORDER_LOGICAL_AND, Blockly.JavaScript.ORDER_LOGICAL_AND], + // a || (b || c) -> a || b || c + [Blockly.JavaScript.ORDER_LOGICAL_OR, Blockly.JavaScript.ORDER_LOGICAL_OR] +]; + +/** + * Initialise the database of variable names. + * @param {!Blockly.Workspace} workspace Workspace to generate code from. + */ +Blockly.JavaScript.init = function(workspace) { + // Create a dictionary of definitions to be printed before the code. + Blockly.JavaScript.definitions_ = Object.create(null); + // Create a dictionary mapping desired function names in definitions_ + // to actual function names (to avoid collisions with user functions). + Blockly.JavaScript.functionNames_ = Object.create(null); + + if (!Blockly.JavaScript.variableDB_) { + Blockly.JavaScript.variableDB_ = + new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_); + } else { + Blockly.JavaScript.variableDB_.reset(); + } + + var defvars = []; + var variables = workspace.variableList; + if (variables.length) { + for (var i = 0; i < variables.length; i++) { + defvars[i] = Blockly.JavaScript.variableDB_.getName(variables[i], + Blockly.Variables.NAME_TYPE); + } + Blockly.JavaScript.definitions_['variables'] = + 'var ' + defvars.join(', ') + ';'; + } +}; + +/** + * Prepend the generated code with the variable definitions. + * @param {string} code Generated code. + * @return {string} Completed code. + */ +Blockly.JavaScript.finish = function(code) { + // Convert the definitions dictionary into a list. + var definitions = []; + for (var name in Blockly.JavaScript.definitions_) { + definitions.push(Blockly.JavaScript.definitions_[name]); + } + // Clean up temporary data. + delete Blockly.JavaScript.definitions_; + delete Blockly.JavaScript.functionNames_; + Blockly.JavaScript.variableDB_.reset(); + return definitions.join('\n\n') + '\n\n\n' + code; +}; + +/** + * Naked values are top-level blocks with outputs that aren't plugged into + * anything. A trailing semicolon is needed to make this legal. + * @param {string} line Line of generated code. + * @return {string} Legal line of code. + */ +Blockly.JavaScript.scrubNakedValue = function(line) { + return line + ';\n'; +}; + +/** + * Encode a string as a properly escaped JavaScript string, complete with + * quotes. + * @param {string} string Text to encode. + * @return {string} JavaScript string. + * @private + */ +Blockly.JavaScript.quote_ = function(string) { + // Can't use goog.string.quote since Google's style guide recommends + // JS string literals use single quotes. + string = string.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\\n') + .replace(/'/g, '\\\''); + return '\'' + string + '\''; +}; + +/** + * Common tasks for generating JavaScript from blocks. + * Handles comments for the specified block and any connected value blocks. + * Calls any statements following this block. + * @param {!Blockly.Block} block The current block. + * @param {string} code The JavaScript code created for this block. + * @return {string} JavaScript code with comments and subsequent blocks added. + * @private + */ +Blockly.JavaScript.scrub_ = function(block, code) { + var commentCode = ''; + // Only collect comments for blocks that aren't inline. + if (!block.outputConnection || !block.outputConnection.targetConnection) { + // Collect comment for this block. + var comment = block.getCommentText(); + comment = Blockly.utils.wrap(comment, Blockly.JavaScript.COMMENT_WRAP - 3); + if (comment) { + if (block.getProcedureDef) { + // Use a comment block for function comments. + commentCode += '/**\n' + + Blockly.JavaScript.prefixLines(comment + '\n', ' * ') + + ' */\n'; + } else { + commentCode += Blockly.JavaScript.prefixLines(comment + '\n', '// '); + } + } + // Collect comments for all value arguments. + // Don't collect comments for nested statements. + for (var i = 0; i < block.inputList.length; i++) { + if (block.inputList[i].type == Blockly.INPUT_VALUE) { + var childBlock = block.inputList[i].connection.targetBlock(); + if (childBlock) { + var comment = Blockly.JavaScript.allNestedComments(childBlock); + if (comment) { + commentCode += Blockly.JavaScript.prefixLines(comment, '// '); + } + } + } + } + } + var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); + var nextCode = Blockly.JavaScript.blockToCode(nextBlock); + return commentCode + code + nextCode; +}; + +/** + * Gets a property and adjusts the value while taking into account indexing. + * @param {!Blockly.Block} block The block. + * @param {string} atId The property ID of the element to get. + * @param {number=} opt_delta Value to add. + * @param {boolean=} opt_negate Whether to negate the value. + * @param {number=} opt_order The highest order acting on this value. + * @return {string|number} + */ +Blockly.JavaScript.getAdjusted = function(block, atId, opt_delta, opt_negate, + opt_order) { + var delta = opt_delta || 0; + var order = opt_order || Blockly.JavaScript.ORDER_NONE; + if (block.workspace.options.oneBasedIndex) { + delta--; + } + var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; + if (delta > 0) { + var at = Blockly.JavaScript.valueToCode(block, atId, + Blockly.JavaScript.ORDER_ADDITION) || defaultAtIndex; + } else if (delta < 0) { + var at = Blockly.JavaScript.valueToCode(block, atId, + Blockly.JavaScript.ORDER_SUBTRACTION) || defaultAtIndex; + } else if (opt_negate) { + var at = Blockly.JavaScript.valueToCode(block, atId, + Blockly.JavaScript.ORDER_UNARY_NEGATION) || defaultAtIndex; + } else { + var at = Blockly.JavaScript.valueToCode(block, atId, order) || + defaultAtIndex; + } + + if (Blockly.isNumber(at)) { + // If the index is a naked number, adjust it right now. + at = parseFloat(at) + delta; + if (opt_negate) { + at = -at; + } + } else { + // If the index is dynamic, adjust it in code. + if (delta > 0) { + at = at + ' + ' + delta; + var innerOrder = Blockly.JavaScript.ORDER_ADDITION; + } else if (delta < 0) { + at = at + ' - ' + -delta; + var innerOrder = Blockly.JavaScript.ORDER_SUBTRACTION; + } + if (opt_negate) { + if (delta) { + at = '-(' + at + ')'; + } else { + at = '-' + at; + } + var innerOrder = Blockly.JavaScript.ORDER_UNARY_NEGATION; + } + innerOrder = Math.floor(innerOrder); + order = Math.floor(order); + if (innerOrder && order >= innerOrder) { + at = '(' + at + ')'; + } + } + return at; +}; diff --git a/Blockly/brobot/generators/javascript/brobot.js b/Blockly/brobot/generators/javascript/brobot.js new file mode 100644 index 0000000..4236a5b --- /dev/null +++ b/Blockly/brobot/generators/javascript/brobot.js @@ -0,0 +1,161 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating JavaScript for colour blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.JavaScript.brobot'); + +goog.require('Blockly.JavaScript'); + + +Blockly.JavaScript['moveforward'] = function(block) { + var code = "var datavalue='MV=50,'+(Math.round(STEPSMETER*0.4))+','+(Math.round(STEPSMETER*0.4));\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + code += 'var dt = new Date();while ((new Date()) - dt <= 3700) {};\n'; // delay + return code; +}; + +Blockly.JavaScript['movebackward'] = function(block) { + var code = "var datavalue='MV=50,'+(-Math.round(STEPSMETER*0.4))+','+(-Math.round(STEPSMETER*0.4));\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + code += 'var dt = new Date();while ((new Date()) - dt <= 3700) {};\n'; // delay + return code; +}; + +Blockly.JavaScript['turnleft'] = function(block) { + var code = "var datavalue='MV=50,'+(-Math.round(STEPSTURN/4))+','+(Math.round(STEPSTURN/4));\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + code += 'var dt = new Date();while ((new Date()) - dt <= 2200) {};\n'; // delay + return code; +}; + +Blockly.JavaScript['turnright'] = function(block) { + var code = "var datavalue='MV=50,'+(Math.round(STEPSTURN/4))+','+(-Math.round(STEPSTURN/4));\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + code += 'var dt = new Date();while ((new Date()) - dt <= 2200) {};\n'; // delay + return code; +}; + +Blockly.JavaScript['turn180'] = function(block) { + var value = block.getFieldValue('turn'); + var code; + if (value==1) + code = "var datavalue='MV=50,'+(-Math.round(STEPSTURN/2))+','+(Math.round(STEPSTURN/2));\n"; + else + code = "var datavalue='MV=50,'+(Math.round(STEPSTURN/2))+','+(-Math.round(STEPSTURN/2));\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + code += 'var dt = new Date();while ((new Date()) - dt <= 3600) {};\n'; // delay + return code; +}; + +Blockly.JavaScript['spin360'] = function(block) { + var value = block.getFieldValue('spin'); + var code; + if (value==1) + code = "var datavalue='MV=50,'+(-Math.round(STEPSTURN))+','+(Math.round(STEPSTURN));\n"; + else + code = "var datavalue='MV=50,'+(Math.round(STEPSTURN))+','+(-Math.round(STEPSTURN));\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + code += 'var dt = new Date();while ((new Date()) - dt <= 5400) {};\n'; // delay + return code; +}; + +Blockly.JavaScript['movesimple'] = function(block) { + var value = Blockly.JavaScript.valueToCode(block, 'cm', Blockly.JavaScript.ORDER_ATOMIC); + var value2 = block.getFieldValue('move'); + var code; + if (value2 == 0) + code = "var datavalue='MV=50,"+(Math.round(value*STEPSMETER/100))+","+(Math.round(value*STEPSMETER/100))+"';\n"; + else + code = "var datavalue='MV=50,"+(-Math.round(value*STEPSMETER/100))+","+(-Math.round(value*STEPSMETER/100))+"';\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + var delay = 51*Math.abs(value) + 1200; + code += 'var dt = new Date();while ((new Date()) - dt <= '+delay+') {};\n'; // delay + return code; +}; + +Blockly.JavaScript['turndegrees'] = function(block) { + var value = Blockly.JavaScript.valueToCode(block, 'degrees', Blockly.JavaScript.ORDER_ATOMIC); + var value2 = block.getFieldValue('turn'); + var code; + if (value2 == 1) + code = "var datavalue='MV=50,"+(-Math.round(value*STEPSTURN/360))+","+(Math.round(value*STEPSTURN/360))+"';\n"; + else + code = "var datavalue='MV=50,"+(Math.round(value*STEPSTURN/360))+","+(-Math.round(value*STEPSTURN/360))+"';\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + var delay = 16*Math.abs(value)+700; + code += 'var dt = new Date();while ((new Date()) - dt <= '+delay+') {};\n'; // delay + return code; +}; + +Blockly.JavaScript['robotconfig'] = function(block) { + var IPvalue = Blockly.JavaScript.valueToCode(block, 'IPvalue', Blockly.JavaScript.ORDER_ATOMIC).replace(/'/g, ""); + //var PORTvalue = Blockly.JavaScript.valueToCode(block, 'PORTvalue', Blockly.JavaScript.ORDER_ATOMIC).replace(/'/g, ""); + var PORTvalue = "2222" + var code = '//Robot Initialization\n\n'; + code += "$.ajax({url:'http://127.0.0.1:8008', data:\"IP="+ IPvalue+"&PORT="+PORTvalue+"\"});\n"; + return code; +} + +Blockly.JavaScript['throttle'] = function(block) { + var value = Blockly.JavaScript.valueToCode(block, 'TValue', Blockly.JavaScript.ORDER_ATOMIC); + var code = "var datavalue='TH='+"+value+";\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + return code; +}; + +Blockly.JavaScript['steering'] = function(block) { + var value = Blockly.JavaScript.valueToCode(block, 'SValue', Blockly.JavaScript.ORDER_ATOMIC); + var code = "var datavalue='ST='+"+value+";\n"; + code += "$.ajax({url:'http://127.0.0.1:8008', data: datavalue});\n"; + return code; +}; + +Blockly.JavaScript['servo'] = function(block) { + //var value = Blockly.JavaScript.valueToCode(block, 'SValue', Blockly.JavaScript.ORDER_ATOMIC);// + var value = block.getFieldValue('Servo'); + // TODO: Assemble JavaScript into code variable. + var code = "$.ajax({url:'http://127.0.0.1:8008', data:'SE="+ value+"'});\n"; + return code; +}; + +Blockly.JavaScript['mode'] = function(block) { + //var value = Blockly.JavaScript.valueToCode(block, 'SValue', Blockly.JavaScript.ORDER_ATOMIC);// + var value = block.getFieldValue('Mode'); + // TODO: Assemble JavaScript into code variable. + var code = "$.ajax({url:'http://127.0.0.1:8008', data:'MO="+ value+"'});\n"; + return code; +}; + +Blockly.JavaScript['delay'] = function(block) { + //var value = Blockly.JavaScript.valueToCode(block, 'SValue', Blockly.JavaScript.ORDER_ATOMIC);// + var value = block.getFieldValue('DValue')*1000; + // TODO: Assemble JavaScript into code variable. + //var code = 'window.alert(delay'+value+');\n'; + var end = 0; + var code = 'var dt = new Date();while ((new Date()) - dt <= '+value+') {};\n'; + return code; +}; + + diff --git a/Blockly/brobot/generators/python.js b/Blockly/brobot/generators/python.js new file mode 100644 index 0000000..3b7aa57 --- /dev/null +++ b/Blockly/brobot/generators/python.js @@ -0,0 +1,283 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Helper functions for generating Python for blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Python'); + +goog.require('Blockly.Generator'); + + +/** + * Python code generator. + * @type {!Blockly.Generator} + */ +Blockly.Python = new Blockly.Generator('Python'); + +/** + * List of illegal variable names. + * This is not intended to be a security feature. Blockly is 100% client-side, + * so bypassing this list is trivial. This is intended to prevent users from + * accidentally clobbering a built-in object or function. + * @private + */ +Blockly.Python.addReservedWords( + // import keyword + // print ','.join(keyword.kwlist) + // http://docs.python.org/reference/lexical_analysis.html#keywords + 'and,as,assert,break,class,continue,def,del,elif,else,except,exec,' + + 'finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,' + + 'return,try,while,with,yield,' + + //http://docs.python.org/library/constants.html + 'True,False,None,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,' + + 'license,credits,' + + // http://docs.python.org/library/functions.html + 'abs,divmod,input,open,staticmethod,all,enumerate,int,ord,str,any,eval,' + + 'isinstance,pow,sum,basestring,execfile,issubclass,print,super,bin,file,' + + 'iter,property,tuple,bool,filter,len,range,type,bytearray,float,list,' + + 'raw_input,unichr,callable,format,locals,reduce,unicode,chr,frozenset,' + + 'long,reload,vars,classmethod,getattr,map,repr,xrange,cmp,globals,max,' + + 'reversed,zip,compile,hasattr,memoryview,round,__import__,complex,hash,' + + 'min,set,apply,delattr,help,next,setattr,buffer,dict,hex,object,slice,' + + 'coerce,dir,id,oct,sorted,intern' +); + +/** + * Order of operation ENUMs. + * http://docs.python.org/reference/expressions.html#summary + */ +Blockly.Python.ORDER_ATOMIC = 0; // 0 "" ... +Blockly.Python.ORDER_COLLECTION = 1; // tuples, lists, dictionaries +Blockly.Python.ORDER_STRING_CONVERSION = 1; // `expression...` +Blockly.Python.ORDER_MEMBER = 2.1; // . [] +Blockly.Python.ORDER_FUNCTION_CALL = 2.2; // () +Blockly.Python.ORDER_EXPONENTIATION = 3; // ** +Blockly.Python.ORDER_UNARY_SIGN = 4; // + - +Blockly.Python.ORDER_BITWISE_NOT = 4; // ~ +Blockly.Python.ORDER_MULTIPLICATIVE = 5; // * / // % +Blockly.Python.ORDER_ADDITIVE = 6; // + - +Blockly.Python.ORDER_BITWISE_SHIFT = 7; // << >> +Blockly.Python.ORDER_BITWISE_AND = 8; // & +Blockly.Python.ORDER_BITWISE_XOR = 9; // ^ +Blockly.Python.ORDER_BITWISE_OR = 10; // | +Blockly.Python.ORDER_RELATIONAL = 11; // in, not in, is, is not, + // <, <=, >, >=, <>, !=, == +Blockly.Python.ORDER_LOGICAL_NOT = 12; // not +Blockly.Python.ORDER_LOGICAL_AND = 13; // and +Blockly.Python.ORDER_LOGICAL_OR = 14; // or +Blockly.Python.ORDER_CONDITIONAL = 15; // if else +Blockly.Python.ORDER_LAMBDA = 16; // lambda +Blockly.Python.ORDER_NONE = 99; // (...) + +/** + * List of outer-inner pairings that do NOT require parentheses. + * @type {!Array.>} + */ +Blockly.Python.ORDER_OVERRIDES = [ + // (foo()).bar -> foo().bar + // (foo())[0] -> foo()[0] + [Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_MEMBER], + // (foo())() -> foo()() + [Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_FUNCTION_CALL], + // (foo.bar).baz -> foo.bar.baz + // (foo.bar)[0] -> foo.bar[0] + // (foo[0]).bar -> foo[0].bar + // (foo[0])[1] -> foo[0][1] + [Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_MEMBER], + // (foo.bar)() -> foo.bar() + // (foo[0])() -> foo[0]() + [Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_FUNCTION_CALL], + + // not (not foo) -> not not foo + [Blockly.Python.ORDER_LOGICAL_NOT, Blockly.Python.ORDER_LOGICAL_NOT], + // a and (b and c) -> a and b and c + [Blockly.Python.ORDER_LOGICAL_AND, Blockly.Python.ORDER_LOGICAL_AND], + // a or (b or c) -> a or b or c + [Blockly.Python.ORDER_LOGICAL_OR, Blockly.Python.ORDER_LOGICAL_OR] +]; + +/** + * Initialise the database of variable names. + * @param {!Blockly.Workspace} workspace Workspace to generate code from. + */ +Blockly.Python.init = function(workspace) { + /** + * Empty loops or conditionals are not allowed in Python. + */ + Blockly.Python.PASS = this.INDENT + 'pass\n'; + // Create a dictionary of definitions to be printed before the code. + Blockly.Python.definitions_ = Object.create(null); + // Create a dictionary mapping desired function names in definitions_ + // to actual function names (to avoid collisions with user functions). + Blockly.Python.functionNames_ = Object.create(null); + + if (!Blockly.Python.variableDB_) { + Blockly.Python.variableDB_ = + new Blockly.Names(Blockly.Python.RESERVED_WORDS_); + } else { + Blockly.Python.variableDB_.reset(); + } + + var defvars = []; + var variables = workspace.variableList; + for (var i = 0; i < variables.length; i++) { + defvars[i] = Blockly.Python.variableDB_.getName(variables[i], + Blockly.Variables.NAME_TYPE) + ' = None'; + } + Blockly.Python.definitions_['variables'] = defvars.join('\n'); +}; + +/** + * Prepend the generated code with the variable definitions. + * @param {string} code Generated code. + * @return {string} Completed code. + */ +Blockly.Python.finish = function(code) { + // Convert the definitions dictionary into a list. + var imports = []; + var definitions = []; + for (var name in Blockly.Python.definitions_) { + var def = Blockly.Python.definitions_[name]; + if (def.match(/^(from\s+\S+\s+)?import\s+\S+/)) { + imports.push(def); + } else { + definitions.push(def); + } + } + // Clean up temporary data. + delete Blockly.Python.definitions_; + delete Blockly.Python.functionNames_; + Blockly.Python.variableDB_.reset(); + var allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n'); + return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code; +}; + +/** + * Naked values are top-level blocks with outputs that aren't plugged into + * anything. + * @param {string} line Line of generated code. + * @return {string} Legal line of code. + */ +Blockly.Python.scrubNakedValue = function(line) { + return line + '\n'; +}; + +/** + * Encode a string as a properly escaped Python string, complete with quotes. + * @param {string} string Text to encode. + * @return {string} Python string. + * @private + */ +Blockly.Python.quote_ = function(string) { + // Can't use goog.string.quote since % must also be escaped. + string = string.replace(/\\/g, '\\\\') + .replace(/\n/g, '\\\n') + .replace(/\%/g, '\\%') + .replace(/'/g, '\\\''); + return '\'' + string + '\''; +}; + +/** + * Common tasks for generating Python from blocks. + * Handles comments for the specified block and any connected value blocks. + * Calls any statements following this block. + * @param {!Blockly.Block} block The current block. + * @param {string} code The Python code created for this block. + * @return {string} Python code with comments and subsequent blocks added. + * @private + */ +Blockly.Python.scrub_ = function(block, code) { + var commentCode = ''; + // Only collect comments for blocks that aren't inline. + if (!block.outputConnection || !block.outputConnection.targetConnection) { + // Collect comment for this block. + var comment = block.getCommentText(); + comment = Blockly.utils.wrap(comment, Blockly.Python.COMMENT_WRAP - 3); + if (comment) { + if (block.getProcedureDef) { + // Use a comment block for function comments. + commentCode += '"""' + comment + '\n"""\n'; + } else { + commentCode += Blockly.Python.prefixLines(comment + '\n', '# '); + } + } + // Collect comments for all value arguments. + // Don't collect comments for nested statements. + for (var i = 0; i < block.inputList.length; i++) { + if (block.inputList[i].type == Blockly.INPUT_VALUE) { + var childBlock = block.inputList[i].connection.targetBlock(); + if (childBlock) { + var comment = Blockly.Python.allNestedComments(childBlock); + if (comment) { + commentCode += Blockly.Python.prefixLines(comment, '# '); + } + } + } + } + } + var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); + var nextCode = Blockly.Python.blockToCode(nextBlock); + return commentCode + code + nextCode; +}; + +/** + * Gets a property and adjusts the value, taking into account indexing, and + * casts to an integer. + * @param {!Blockly.Block} block The block. + * @param {string} atId The property ID of the element to get. + * @param {number=} opt_delta Value to add. + * @param {boolean=} opt_negate Whether to negate the value. + * @return {string|number} + */ +Blockly.Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) { + var delta = opt_delta || 0; + if (block.workspace.options.oneBasedIndex) { + delta--; + } + var defaultAtIndex = block.workspace.options.oneBasedIndex ? '1' : '0'; + var atOrder = delta ? Blockly.Python.ORDER_ADDITIVE : + Blockly.Python.ORDER_NONE; + var at = Blockly.Python.valueToCode(block, atId, atOrder) || defaultAtIndex; + + if (Blockly.isNumber(at)) { + // If the index is a naked number, adjust it right now. + at = parseInt(at, 10) + delta; + if (opt_negate) { + at = -at; + } + } else { + // If the index is dynamic, adjust it in code. + if (delta > 0) { + at = 'int(' + at + ' + ' + delta + ')'; + } else if (delta < 0) { + at = 'int(' + at + ' - ' + -delta + ')'; + } else { + at = 'int(' + at + ')'; + } + if (opt_negate) { + at = '-' + at; + } + } + return at; +}; diff --git a/Blockly/brobot/generators/python/brobot.js b/Blockly/brobot/generators/python/brobot.js new file mode 100644 index 0000000..b429210 --- /dev/null +++ b/Blockly/brobot/generators/python/brobot.js @@ -0,0 +1,83 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating JavaScript for colour blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Python.brobot'); + +goog.require('Blockly.Python'); + +Blockly.Python['robotconfig'] = function(block) { + var IPvalue = Blockly.JavaScript.valueToCode(block, 'IPvalue', Blockly.JavaScript.ORDER_ATOMIC).replace(/'/g, ""); + var PORTvalue = Blockly.JavaScript.valueToCode(block, 'PORTvalue', Blockly.JavaScript.ORDER_ATOMIC).replace(/'/g, ""); + var code = 'myRobot.UDP_IP=\"'+IPvalue+'\"\n'; + code += 'myRobot.UDP_PORT=\"'+PORTvalue+'\"\n'; + //var code = ''; + return code; +}; + +Blockly.Python['throttle'] = function(block) { + var value = Blockly.JavaScript.valueToCode(block, 'TValue', Blockly.JavaScript.ORDER_ATOMIC);// + //var value = block.getFieldValue('TValue'); + // TODO: Assemble JavaScript into code variable. + //var code = 'window.alert("T'+value+'");\n'; + // Create the Socket + var code = 'myRobot.throttle('+value+')\n'; + return code; +}; + +Blockly.Python['steering'] = function(block) { + var value = Blockly.JavaScript.valueToCode(block, 'SValue', Blockly.JavaScript.ORDER_ATOMIC);// + //var value = block.getFieldValue('SValue'); + // TODO: Assemble JavaScript into code variable. + var code = 'myRobot.steering('+value+')\n'; + return code; +}; + +Blockly.Python['servo'] = function(block) { + //var value = Blockly.JavaScript.valueToCode(block, 'SValue', Blockly.JavaScript.ORDER_ATOMIC);// + var value = block.getFieldValue('Servo'); + // TODO: Assemble JavaScript into code variable. + var code = 'myRobot.servo('+value+')\n'; + return code; +}; + +Blockly.Python['mode'] = function(block) { + //var value = Blockly.JavaScript.valueToCode(block, 'SValue', Blockly.JavaScript.ORDER_ATOMIC);// + var value = block.getFieldValue('Mode'); + // TODO: Assemble JavaScript into code variable. + var code = 'myRobot.mode('+value+')\n'; + return code; +}; + +Blockly.Python['delay'] = function(block) { + //var value = Blockly.JavaScript.valueToCode(block, 'SValue', Blockly.JavaScript.ORDER_ATOMIC);// + var value = block.getFieldValue('DValue'); + // TODO: Assemble JavaScript into code variable. + //var code = 'window.alert(delay'+value+');\n'; + var code = 'time.sleep('+value+')\n'; + return code; +}; + + diff --git a/Blockly/brobot/generators/python/colour.js b/Blockly/brobot/generators/python/colour.js new file mode 100644 index 0000000..68666a8 --- /dev/null +++ b/Blockly/brobot/generators/python/colour.js @@ -0,0 +1,86 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for colour blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Python.colour'); + +goog.require('Blockly.Python'); + + +Blockly.Python['colour_picker'] = function(block) { + // Colour picker. + var code = '\'' + block.getFieldValue('COLOUR') + '\''; + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['colour_random'] = function(block) { + // Generate a random colour. + Blockly.Python.definitions_['import_random'] = 'import random'; + var code = '\'#%06x\' % random.randint(0, 2**24 - 1)'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['colour_rgb'] = function(block) { + // Compose a colour from RGB components expressed as percentages. + var functionName = Blockly.Python.provideFunction_( + 'colour_rgb', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b):', + ' r = round(min(100, max(0, r)) * 2.55)', + ' g = round(min(100, max(0, g)) * 2.55)', + ' b = round(min(100, max(0, b)) * 2.55)', + ' return \'#%02x%02x%02x\' % (r, g, b)']); + var r = Blockly.Python.valueToCode(block, 'RED', + Blockly.Python.ORDER_NONE) || 0; + var g = Blockly.Python.valueToCode(block, 'GREEN', + Blockly.Python.ORDER_NONE) || 0; + var b = Blockly.Python.valueToCode(block, 'BLUE', + Blockly.Python.ORDER_NONE) || 0; + var code = functionName + '(' + r + ', ' + g + ', ' + b + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['colour_blend'] = function(block) { + // Blend two colours together. + var functionName = Blockly.Python.provideFunction_( + 'colour_blend', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + + '(colour1, colour2, ratio):', + ' r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)', + ' g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)', + ' b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)', + ' ratio = min(1, max(0, ratio))', + ' r = round(r1 * (1 - ratio) + r2 * ratio)', + ' g = round(g1 * (1 - ratio) + g2 * ratio)', + ' b = round(b1 * (1 - ratio) + b2 * ratio)', + ' return \'#%02x%02x%02x\' % (r, g, b)']); + var colour1 = Blockly.Python.valueToCode(block, 'COLOUR1', + Blockly.Python.ORDER_NONE) || '\'#000000\''; + var colour2 = Blockly.Python.valueToCode(block, 'COLOUR2', + Blockly.Python.ORDER_NONE) || '\'#000000\''; + var ratio = Blockly.Python.valueToCode(block, 'RATIO', + Blockly.Python.ORDER_NONE) || 0; + var code = functionName + '(' + colour1 + ', ' + colour2 + ', ' + ratio + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; diff --git a/Blockly/brobot/generators/python/lists.js b/Blockly/brobot/generators/python/lists.js new file mode 100644 index 0000000..84618f8 --- /dev/null +++ b/Blockly/brobot/generators/python/lists.js @@ -0,0 +1,355 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for list blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.lists'); + +goog.require('Blockly.Python'); + + +Blockly.Python['lists_create_empty'] = function(block) { + // Create an empty list. + return ['[]', Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['lists_create_with'] = function(block) { + // Create a list with any number of elements of any type. + var elements = new Array(block.itemCount_); + for (var i = 0; i < block.itemCount_; i++) { + elements[i] = Blockly.Python.valueToCode(block, 'ADD' + i, + Blockly.Python.ORDER_NONE) || 'None'; + } + var code = '[' + elements.join(', ') + ']'; + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['lists_repeat'] = function(block) { + // Create a list with one element repeated. + var item = Blockly.Python.valueToCode(block, 'ITEM', + Blockly.Python.ORDER_NONE) || 'None'; + var times = Blockly.Python.valueToCode(block, 'NUM', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + var code = '[' + item + '] * ' + times; + return [code, Blockly.Python.ORDER_MULTIPLICATIVE]; +}; + +Blockly.Python['lists_length'] = function(block) { + // String or array length. + var list = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '[]'; + return ['len(' + list + ')', Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['lists_isEmpty'] = function(block) { + // Is the string null or array empty? + var list = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '[]'; + var code = 'not len(' + list + ')'; + return [code, Blockly.Python.ORDER_LOGICAL_NOT]; +}; + +Blockly.Python['lists_indexOf'] = function(block) { + // Find an item in the list. + var item = Blockly.Python.valueToCode(block, 'FIND', + Blockly.Python.ORDER_NONE) || '[]'; + var list = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '\'\''; + if (block.workspace.options.oneBasedIndex) { + var errorIndex = ' 0'; + var firstIndexAdjustment = ' + 1'; + var lastIndexAdjustment = ''; + } else { + var errorIndex = ' -1'; + var firstIndexAdjustment = ''; + var lastIndexAdjustment = ' - 1'; + } + if (block.getFieldValue('END') == 'FIRST') { + var functionName = Blockly.Python.provideFunction_( + 'first_index', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + + '(my_list, elem):', + ' try: index = my_list.index(elem)' + firstIndexAdjustment, + ' except: index =' + errorIndex, + ' return index']); + var code = functionName + '(' + list + ', ' + item + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } + var functionName = Blockly.Python.provideFunction_( + 'last_index', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(my_list, elem):', + ' try: index = len(my_list) - my_list[::-1].index(elem)' + + lastIndexAdjustment, + ' except: index =' + errorIndex, + ' return index']); + var code = functionName + '(' + list + ', ' + item + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['lists_getIndex'] = function(block) { + // Get element at index. + // Note: Until January 2013 this block did not have MODE or WHERE inputs. + var mode = block.getFieldValue('MODE') || 'GET'; + var where = block.getFieldValue('WHERE') || 'FROM_START'; + var listOrder = (where == 'RANDOM') ? Blockly.Python.ORDER_NONE : + Blockly.Python.ORDER_MEMBER; + var list = Blockly.Python.valueToCode(block, 'VALUE', listOrder) || '[]'; + + switch (where) { + case 'FIRST': + if (mode == 'GET') { + var code = list + '[0]'; + return [code, Blockly.Python.ORDER_MEMBER]; + } else if (mode == 'GET_REMOVE') { + var code = list + '.pop(0)'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return list + '.pop(0)\n'; + } + break; + case 'LAST': + if (mode == 'GET') { + var code = list + '[-1]'; + return [code, Blockly.Python.ORDER_MEMBER]; + } else if (mode == 'GET_REMOVE') { + var code = list + '.pop()'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return list + '.pop()\n'; + } + break; + case 'FROM_START': + var at = Blockly.Python.getAdjustedInt(block, 'AT'); + if (mode == 'GET') { + var code = list + '[' + at + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; + } else if (mode == 'GET_REMOVE') { + var code = list + '.pop(' + at + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return list + '.pop(' + at + ')\n'; + } + break; + case'FROM_END': + var at = Blockly.Python.getAdjustedInt(block, 'AT', 1, true); + if (mode == 'GET') { + var code = list + '[' + at + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; + } else if (mode == 'GET_REMOVE') { + var code = list + '.pop(' + at + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return list + '.pop(' + at + ')\n'; + } + break; + case 'RANDOM': + Blockly.Python.definitions_['import_random'] = 'import random'; + if (mode == 'GET') { + code = 'random.choice(' + list + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else { + var functionName = Blockly.Python.provideFunction_( + 'lists_remove_random_item', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', + ' x = int(random.random() * len(myList))', + ' return myList.pop(x)']); + code = functionName + '(' + list + ')'; + if (mode == 'GET_REMOVE') { + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } else if (mode == 'REMOVE') { + return code + '\n'; + } + } + break; + } + throw 'Unhandled combination (lists_getIndex).'; +}; + +Blockly.Python['lists_setIndex'] = function(block) { + // Set element at index. + // Note: Until February 2013 this block did not have MODE or WHERE inputs. + var list = Blockly.Python.valueToCode(block, 'LIST', + Blockly.Python.ORDER_MEMBER) || '[]'; + var mode = block.getFieldValue('MODE') || 'GET'; + var where = block.getFieldValue('WHERE') || 'FROM_START'; + var value = Blockly.Python.valueToCode(block, 'TO', + Blockly.Python.ORDER_NONE) || 'None'; + // Cache non-trivial values to variables to prevent repeated look-ups. + // Closure, which accesses and modifies 'list'. + function cacheList() { + if (list.match(/^\w+$/)) { + return ''; + } + var listVar = Blockly.Python.variableDB_.getDistinctName( + 'tmp_list', Blockly.Variables.NAME_TYPE); + var code = listVar + ' = ' + list + '\n'; + list = listVar; + return code; + } + + switch (where) { + case 'FIRST': + if (mode == 'SET') { + return list + '[0] = ' + value + '\n'; + } else if (mode == 'INSERT') { + return list + '.insert(0, ' + value + ')\n'; + } + break; + case 'LAST': + if (mode == 'SET') { + return list + '[-1] = ' + value + '\n'; + } else if (mode == 'INSERT') { + return list + '.append(' + value + ')\n'; + } + break; + case 'FROM_START': + var at = Blockly.Python.getAdjustedInt(block, 'AT'); + if (mode == 'SET') { + return list + '[' + at + '] = ' + value + '\n'; + } else if (mode == 'INSERT') { + return list + '.insert(' + at + ', ' + value + ')\n'; + } + break; + case 'FROM_END': + var at = Blockly.Python.getAdjustedInt(block, 'AT', 1, true); + if (mode == 'SET') { + return list + '[' + at + '] = ' + value + '\n'; + } else if (mode == 'INSERT') { + return list + '.insert(' + at + ', ' + value + ')\n'; + } + break; + case 'RANDOM': + Blockly.Python.definitions_['import_random'] = 'import random'; + var code = cacheList(); + var xVar = Blockly.Python.variableDB_.getDistinctName( + 'tmp_x', Blockly.Variables.NAME_TYPE); + code += xVar + ' = int(random.random() * len(' + list + '))\n'; + if (mode == 'SET') { + code += list + '[' + xVar + '] = ' + value + '\n'; + return code; + } else if (mode == 'INSERT') { + code += list + '.insert(' + xVar + ', ' + value + ')\n'; + return code; + } + break; + } + throw 'Unhandled combination (lists_setIndex).'; +}; + +Blockly.Python['lists_getSublist'] = function(block) { + // Get sublist. + var list = Blockly.Python.valueToCode(block, 'LIST', + Blockly.Python.ORDER_MEMBER) || '[]'; + var where1 = block.getFieldValue('WHERE1'); + var where2 = block.getFieldValue('WHERE2'); + switch (where1) { + case 'FROM_START': + var at1 = Blockly.Python.getAdjustedInt(block, 'AT1'); + if (at1 == '0') { + at1 = ''; + } + break; + case 'FROM_END': + var at1 = Blockly.Python.getAdjustedInt(block, 'AT1', 1, true); + break; + case 'FIRST': + var at1 = ''; + break; + default: + throw 'Unhandled option (lists_getSublist)'; + } + switch (where2) { + case 'FROM_START': + var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 1); + break; + case 'FROM_END': + var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 0, true); + // Ensure that if the result calculated is 0 that sub-sequence will + // include all elements as expected. + if (!Blockly.isNumber(String(at2))) { + Blockly.Python.definitions_['import_sys'] = 'import sys'; + at2 += ' or sys.maxsize'; + } else if (at2 == '0') { + at2 = ''; + } + break; + case 'LAST': + var at2 = ''; + break; + default: + throw 'Unhandled option (lists_getSublist)'; + } + var code = list + '[' + at1 + ' : ' + at2 + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; +}; + +Blockly.Python['lists_sort'] = function(block) { + // Block for sorting a list. + var list = (Blockly.Python.valueToCode(block, 'LIST', + Blockly.Python.ORDER_NONE) || '[]'); + var type = block.getFieldValue('TYPE'); + var reverse = block.getFieldValue('DIRECTION') === '1' ? 'False' : 'True'; + var sortFunctionName = Blockly.Python.provideFunction_('lists_sort', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + + '(my_list, type, reverse):', + ' def try_float(s):', + ' try:', + ' return float(s)', + ' except:', + ' return 0', + ' key_funcs = {', + ' "NUMERIC": try_float,', + ' "TEXT": str,', + ' "IGNORE_CASE": lambda s: str(s).lower()', + ' }', + ' key_func = key_funcs[type]', + ' list_cpy = list(my_list)', // Clone the list. + ' return sorted(list_cpy, key=key_func, reverse=reverse)' + ]); + + var code = sortFunctionName + + '(' + list + ', "' + type + '", ' + reverse + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['lists_split'] = function(block) { + // Block for splitting text into a list, or joining a list into text. + var mode = block.getFieldValue('MODE'); + if (mode == 'SPLIT') { + var value_input = Blockly.Python.valueToCode(block, 'INPUT', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var value_delim = Blockly.Python.valueToCode(block, 'DELIM', + Blockly.Python.ORDER_NONE); + var code = value_input + '.split(' + value_delim + ')'; + } else if (mode == 'JOIN') { + var value_input = Blockly.Python.valueToCode(block, 'INPUT', + Blockly.Python.ORDER_NONE) || '[]'; + var value_delim = Blockly.Python.valueToCode(block, 'DELIM', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var code = value_delim + '.join(' + value_input + ')'; + } else { + throw 'Unknown mode: ' + mode; + } + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; diff --git a/Blockly/brobot/generators/python/logic.js b/Blockly/brobot/generators/python/logic.js new file mode 100644 index 0000000..a485e5c --- /dev/null +++ b/Blockly/brobot/generators/python/logic.js @@ -0,0 +1,127 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for logic blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.logic'); + +goog.require('Blockly.Python'); + + +Blockly.Python['controls_if'] = function(block) { + // If/elseif/else condition. + var n = 0; + var argument = Blockly.Python.valueToCode(block, 'IF' + n, + Blockly.Python.ORDER_NONE) || 'False'; + var branch = Blockly.Python.statementToCode(block, 'DO' + n) || + Blockly.Python.PASS; + var code = 'if ' + argument + ':\n' + branch; + for (n = 1; n <= block.elseifCount_; n++) { + argument = Blockly.Python.valueToCode(block, 'IF' + n, + Blockly.Python.ORDER_NONE) || 'False'; + branch = Blockly.Python.statementToCode(block, 'DO' + n) || + Blockly.Python.PASS; + code += 'elif ' + argument + ':\n' + branch; + } + if (block.elseCount_) { + branch = Blockly.Python.statementToCode(block, 'ELSE') || + Blockly.Python.PASS; + code += 'else:\n' + branch; + } + return code; +}; + +Blockly.Python['logic_compare'] = function(block) { + // Comparison operator. + var OPERATORS = { + 'EQ': '==', + 'NEQ': '!=', + 'LT': '<', + 'LTE': '<=', + 'GT': '>', + 'GTE': '>=' + }; + var operator = OPERATORS[block.getFieldValue('OP')]; + var order = Blockly.Python.ORDER_RELATIONAL; + var argument0 = Blockly.Python.valueToCode(block, 'A', order) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'B', order) || '0'; + var code = argument0 + ' ' + operator + ' ' + argument1; + return [code, order]; +}; + +Blockly.Python['logic_operation'] = function(block) { + // Operations 'and', 'or'. + var operator = (block.getFieldValue('OP') == 'AND') ? 'and' : 'or'; + var order = (operator == 'and') ? Blockly.Python.ORDER_LOGICAL_AND : + Blockly.Python.ORDER_LOGICAL_OR; + var argument0 = Blockly.Python.valueToCode(block, 'A', order); + var argument1 = Blockly.Python.valueToCode(block, 'B', order); + if (!argument0 && !argument1) { + // If there are no arguments, then the return value is false. + argument0 = 'False'; + argument1 = 'False'; + } else { + // Single missing arguments have no effect on the return value. + var defaultArgument = (operator == 'and') ? 'True' : 'False'; + if (!argument0) { + argument0 = defaultArgument; + } + if (!argument1) { + argument1 = defaultArgument; + } + } + var code = argument0 + ' ' + operator + ' ' + argument1; + return [code, order]; +}; + +Blockly.Python['logic_negate'] = function(block) { + // Negation. + var argument0 = Blockly.Python.valueToCode(block, 'BOOL', + Blockly.Python.ORDER_LOGICAL_NOT) || 'True'; + var code = 'not ' + argument0; + return [code, Blockly.Python.ORDER_LOGICAL_NOT]; +}; + +Blockly.Python['logic_boolean'] = function(block) { + // Boolean values true and false. + var code = (block.getFieldValue('BOOL') == 'TRUE') ? 'True' : 'False'; + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['logic_null'] = function(block) { + // Null data type. + return ['None', Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['logic_ternary'] = function(block) { + // Ternary operator. + var value_if = Blockly.Python.valueToCode(block, 'IF', + Blockly.Python.ORDER_CONDITIONAL) || 'False'; + var value_then = Blockly.Python.valueToCode(block, 'THEN', + Blockly.Python.ORDER_CONDITIONAL) || 'None'; + var value_else = Blockly.Python.valueToCode(block, 'ELSE', + Blockly.Python.ORDER_CONDITIONAL) || 'None'; + var code = value_then + ' if ' + value_if + ' else ' + value_else; + return [code, Blockly.Python.ORDER_CONDITIONAL]; +}; diff --git a/Blockly/brobot/generators/python/loops.js b/Blockly/brobot/generators/python/loops.js new file mode 100644 index 0000000..3cb1ab9 --- /dev/null +++ b/Blockly/brobot/generators/python/loops.js @@ -0,0 +1,211 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for loop blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.loops'); + +goog.require('Blockly.Python'); + + +Blockly.Python['controls_repeat_ext'] = function(block) { + // Repeat n times. + if (block.getField('TIMES')) { + // Internal number. + var repeats = String(parseInt(block.getFieldValue('TIMES'), 10)); + } else { + // External number. + var repeats = Blockly.Python.valueToCode(block, 'TIMES', + Blockly.Python.ORDER_NONE) || '0'; + } + if (Blockly.isNumber(repeats)) { + repeats = parseInt(repeats, 10); + } else { + repeats = 'int(' + repeats + ')'; + } + var branch = Blockly.Python.statementToCode(block, 'DO'); + branch = Blockly.Python.addLoopTrap(branch, block.id) || + Blockly.Python.PASS; + var loopVar = Blockly.Python.variableDB_.getDistinctName( + 'count', Blockly.Variables.NAME_TYPE); + var code = 'for ' + loopVar + ' in range(' + repeats + '):\n' + branch; + return code; +}; + +Blockly.Python['controls_repeat'] = Blockly.Python['controls_repeat_ext']; + +Blockly.Python['controls_whileUntil'] = function(block) { + // Do while/until loop. + var until = block.getFieldValue('MODE') == 'UNTIL'; + var argument0 = Blockly.Python.valueToCode(block, 'BOOL', + until ? Blockly.Python.ORDER_LOGICAL_NOT : + Blockly.Python.ORDER_NONE) || 'False'; + var branch = Blockly.Python.statementToCode(block, 'DO'); + branch = Blockly.Python.addLoopTrap(branch, block.id) || + Blockly.Python.PASS; + if (until) { + argument0 = 'not ' + argument0; + } + return 'while ' + argument0 + ':\n' + branch; +}; + +Blockly.Python['controls_for'] = function(block) { + // For loop. + var variable0 = Blockly.Python.variableDB_.getName( + block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.Python.valueToCode(block, 'FROM', + Blockly.Python.ORDER_NONE) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'TO', + Blockly.Python.ORDER_NONE) || '0'; + var increment = Blockly.Python.valueToCode(block, 'BY', + Blockly.Python.ORDER_NONE) || '1'; + var branch = Blockly.Python.statementToCode(block, 'DO'); + branch = Blockly.Python.addLoopTrap(branch, block.id) || + Blockly.Python.PASS; + + var code = ''; + var range; + + // Helper functions. + var defineUpRange = function() { + return Blockly.Python.provideFunction_( + 'upRange', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + + '(start, stop, step):', + ' while start <= stop:', + ' yield start', + ' start += abs(step)']); + }; + var defineDownRange = function() { + return Blockly.Python.provideFunction_( + 'downRange', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + + '(start, stop, step):', + ' while start >= stop:', + ' yield start', + ' start -= abs(step)']); + }; + // Arguments are legal Python code (numbers or strings returned by scrub()). + var generateUpDownRange = function(start, end, inc) { + return '(' + start + ' <= ' + end + ') and ' + + defineUpRange() + '(' + start + ', ' + end + ', ' + inc + ') or ' + + defineDownRange() + '(' + start + ', ' + end + ', ' + inc + ')'; + }; + + if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) && + Blockly.isNumber(increment)) { + // All parameters are simple numbers. + argument0 = parseFloat(argument0); + argument1 = parseFloat(argument1); + increment = Math.abs(parseFloat(increment)); + if (argument0 % 1 === 0 && argument1 % 1 === 0 && increment % 1 === 0) { + // All parameters are integers. + if (argument0 <= argument1) { + // Count up. + argument1++; + if (argument0 == 0 && increment == 1) { + // If starting index is 0, omit it. + range = argument1; + } else { + range = argument0 + ', ' + argument1; + } + // If increment isn't 1, it must be explicit. + if (increment != 1) { + range += ', ' + increment; + } + } else { + // Count down. + argument1--; + range = argument0 + ', ' + argument1 + ', -' + increment; + } + range = 'range(' + range + ')'; + } else { + // At least one of the parameters is not an integer. + if (argument0 < argument1) { + range = defineUpRange(); + } else { + range = defineDownRange(); + } + range += '(' + argument0 + ', ' + argument1 + ', ' + increment + ')'; + } + } else { + // Cache non-trivial values to variables to prevent repeated look-ups. + var scrub = function(arg, suffix) { + if (Blockly.isNumber(arg)) { + // Simple number. + arg = parseFloat(arg); + } else if (arg.match(/^\w+$/)) { + // Variable. + arg = 'float(' + arg + ')'; + } else { + // It's complicated. + var varName = Blockly.Python.variableDB_.getDistinctName( + variable0 + suffix, Blockly.Variables.NAME_TYPE); + code += varName + ' = float(' + arg + ')\n'; + arg = varName; + } + return arg; + }; + var startVar = scrub(argument0, '_start'); + var endVar = scrub(argument1, '_end'); + var incVar = scrub(increment, '_inc'); + + if (typeof startVar == 'number' && typeof endVar == 'number') { + if (startVar < endVar) { + range = defineUpRange(startVar, endVar, increment); + } else { + range = defineDownRange(startVar, endVar, increment); + } + } else { + // We cannot determine direction statically. + range = generateUpDownRange(startVar, endVar, increment); + } + } + code += 'for ' + variable0 + ' in ' + range + ':\n' + branch; + return code; +}; + +Blockly.Python['controls_forEach'] = function(block) { + // For each loop. + var variable0 = Blockly.Python.variableDB_.getName( + block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); + var argument0 = Blockly.Python.valueToCode(block, 'LIST', + Blockly.Python.ORDER_RELATIONAL) || '[]'; + var branch = Blockly.Python.statementToCode(block, 'DO'); + branch = Blockly.Python.addLoopTrap(branch, block.id) || + Blockly.Python.PASS; + var code = 'for ' + variable0 + ' in ' + argument0 + ':\n' + branch; + return code; +}; + +Blockly.Python['controls_flow_statements'] = function(block) { + // Flow statements: continue, break. + switch (block.getFieldValue('FLOW')) { + case 'BREAK': + return 'break\n'; + case 'CONTINUE': + return 'continue\n'; + } + throw 'Unknown flow statement.'; +}; diff --git a/Blockly/brobot/generators/python/math.js b/Blockly/brobot/generators/python/math.js new file mode 100644 index 0000000..a2595e0 --- /dev/null +++ b/Blockly/brobot/generators/python/math.js @@ -0,0 +1,388 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for math blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.math'); + +goog.require('Blockly.Python'); + + +// If any new block imports any library, add that library name here. +Blockly.Python.addReservedWords('math,random,Number'); + +Blockly.Python['math_number'] = function(block) { + // Numeric value. + var code = parseFloat(block.getFieldValue('NUM')); + var order; + if (code == Infinity) { + code = 'float("inf")'; + order = Blockly.Python.ORDER_FUNCTION_CALL; + } else if (code == -Infinity) { + code = '-float("inf")'; + order = Blockly.Python.ORDER_UNARY_SIGN; + } else { + order = code < 0 ? Blockly.Python.ORDER_UNARY_SIGN : + Blockly.Python.ORDER_ATOMIC; + } + return [code, order]; +}; + +Blockly.Python['math_arithmetic'] = function(block) { + // Basic arithmetic operators, and power. + var OPERATORS = { + 'ADD': [' + ', Blockly.Python.ORDER_ADDITIVE], + 'MINUS': [' - ', Blockly.Python.ORDER_ADDITIVE], + 'MULTIPLY': [' * ', Blockly.Python.ORDER_MULTIPLICATIVE], + 'DIVIDE': [' / ', Blockly.Python.ORDER_MULTIPLICATIVE], + 'POWER': [' ** ', Blockly.Python.ORDER_EXPONENTIATION] + }; + var tuple = OPERATORS[block.getFieldValue('OP')]; + var operator = tuple[0]; + var order = tuple[1]; + var argument0 = Blockly.Python.valueToCode(block, 'A', order) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'B', order) || '0'; + var code = argument0 + operator + argument1; + return [code, order]; + // In case of 'DIVIDE', division between integers returns different results + // in Python 2 and 3. However, is not an issue since Blockly does not + // guarantee identical results in all languages. To do otherwise would + // require every operator to be wrapped in a function call. This would kill + // legibility of the generated code. +}; + +Blockly.Python['math_single'] = function(block) { + // Math operators with single operand. + var operator = block.getFieldValue('OP'); + var code; + var arg; + if (operator == 'NEG') { + // Negation is a special case given its different operator precedence. + var code = Blockly.Python.valueToCode(block, 'NUM', + Blockly.Python.ORDER_UNARY_SIGN) || '0'; + return ['-' + code, Blockly.Python.ORDER_UNARY_SIGN]; + } + Blockly.Python.definitions_['import_math'] = 'import math'; + if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { + arg = Blockly.Python.valueToCode(block, 'NUM', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + } else { + arg = Blockly.Python.valueToCode(block, 'NUM', + Blockly.Python.ORDER_NONE) || '0'; + } + // First, handle cases which generate values that don't need parentheses + // wrapping the code. + switch (operator) { + case 'ABS': + code = 'math.fabs(' + arg + ')'; + break; + case 'ROOT': + code = 'math.sqrt(' + arg + ')'; + break; + case 'LN': + code = 'math.log(' + arg + ')'; + break; + case 'LOG10': + code = 'math.log10(' + arg + ')'; + break; + case 'EXP': + code = 'math.exp(' + arg + ')'; + break; + case 'POW10': + code = 'math.pow(10,' + arg + ')'; + break; + case 'ROUND': + code = 'round(' + arg + ')'; + break; + case 'ROUNDUP': + code = 'math.ceil(' + arg + ')'; + break; + case 'ROUNDDOWN': + code = 'math.floor(' + arg + ')'; + break; + case 'SIN': + code = 'math.sin(' + arg + ' / 180.0 * math.pi)'; + break; + case 'COS': + code = 'math.cos(' + arg + ' / 180.0 * math.pi)'; + break; + case 'TAN': + code = 'math.tan(' + arg + ' / 180.0 * math.pi)'; + break; + } + if (code) { + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } + // Second, handle cases which generate values that may need parentheses + // wrapping the code. + switch (operator) { + case 'ASIN': + code = 'math.asin(' + arg + ') / math.pi * 180'; + break; + case 'ACOS': + code = 'math.acos(' + arg + ') / math.pi * 180'; + break; + case 'ATAN': + code = 'math.atan(' + arg + ') / math.pi * 180'; + break; + default: + throw 'Unknown math operator: ' + operator; + } + return [code, Blockly.Python.ORDER_MULTIPLICATIVE]; +}; + +Blockly.Python['math_constant'] = function(block) { + // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. + var CONSTANTS = { + 'PI': ['math.pi', Blockly.Python.ORDER_MEMBER], + 'E': ['math.e', Blockly.Python.ORDER_MEMBER], + 'GOLDEN_RATIO': ['(1 + math.sqrt(5)) / 2', + Blockly.Python.ORDER_MULTIPLICATIVE], + 'SQRT2': ['math.sqrt(2)', Blockly.Python.ORDER_MEMBER], + 'SQRT1_2': ['math.sqrt(1.0 / 2)', Blockly.Python.ORDER_MEMBER], + 'INFINITY': ['float(\'inf\')', Blockly.Python.ORDER_ATOMIC] + }; + var constant = block.getFieldValue('CONSTANT'); + if (constant != 'INFINITY') { + Blockly.Python.definitions_['import_math'] = 'import math'; + } + return CONSTANTS[constant]; +}; + +Blockly.Python['math_number_property'] = function(block) { + // Check if a number is even, odd, prime, whole, positive, or negative + // or if it is divisible by certain number. Returns true or false. + var number_to_check = Blockly.Python.valueToCode(block, 'NUMBER_TO_CHECK', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + var dropdown_property = block.getFieldValue('PROPERTY'); + var code; + if (dropdown_property == 'PRIME') { + Blockly.Python.definitions_['import_math'] = 'import math'; + Blockly.Python.definitions_['from_numbers_import_Number'] = + 'from numbers import Number'; + var functionName = Blockly.Python.provideFunction_( + 'math_isPrime', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(n):', + ' # https://en.wikipedia.org/wiki/Primality_test#Naive_methods', + ' # If n is not a number but a string, try parsing it.', + ' if not isinstance(n, Number):', + ' try:', + ' n = float(n)', + ' except:', + ' return False', + ' if n == 2 or n == 3:', + ' return True', + ' # False if n is negative, is 1, or not whole,' + + ' or if n is divisible by 2 or 3.', + ' if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:', + ' return False', + ' # Check all the numbers of form 6k +/- 1, up to sqrt(n).', + ' for x in range(6, int(math.sqrt(n)) + 2, 6):', + ' if n % (x - 1) == 0 or n % (x + 1) == 0:', + ' return False', + ' return True']); + code = functionName + '(' + number_to_check + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } + switch (dropdown_property) { + case 'EVEN': + code = number_to_check + ' % 2 == 0'; + break; + case 'ODD': + code = number_to_check + ' % 2 == 1'; + break; + case 'WHOLE': + code = number_to_check + ' % 1 == 0'; + break; + case 'POSITIVE': + code = number_to_check + ' > 0'; + break; + case 'NEGATIVE': + code = number_to_check + ' < 0'; + break; + case 'DIVISIBLE_BY': + var divisor = Blockly.Python.valueToCode(block, 'DIVISOR', + Blockly.Python.ORDER_MULTIPLICATIVE); + // If 'divisor' is some code that evals to 0, Python will raise an error. + if (!divisor || divisor == '0') { + return ['False', Blockly.Python.ORDER_ATOMIC]; + } + code = number_to_check + ' % ' + divisor + ' == 0'; + break; + } + return [code, Blockly.Python.ORDER_RELATIONAL]; +}; + +Blockly.Python['math_change'] = function(block) { + // Add to a variable in place. + Blockly.Python.definitions_['from_numbers_import_Number'] = + 'from numbers import Number'; + var argument0 = Blockly.Python.valueToCode(block, 'DELTA', + Blockly.Python.ORDER_ADDITIVE) || '0'; + var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + return varName + ' = (' + varName + ' if isinstance(' + varName + + ', Number) else 0) + ' + argument0 + '\n'; +}; + +// Rounding functions have a single operand. +Blockly.Python['math_round'] = Blockly.Python['math_single']; +// Trigonometry functions have a single operand. +Blockly.Python['math_trig'] = Blockly.Python['math_single']; + +Blockly.Python['math_on_list'] = function(block) { + // Math functions for lists. + var func = block.getFieldValue('OP'); + var list = Blockly.Python.valueToCode(block, 'LIST', + Blockly.Python.ORDER_NONE) || '[]'; + var code; + switch (func) { + case 'SUM': + code = 'sum(' + list + ')'; + break; + case 'MIN': + code = 'min(' + list + ')'; + break; + case 'MAX': + code = 'max(' + list + ')'; + break; + case 'AVERAGE': + Blockly.Python.definitions_['from_numbers_import_Number'] = + 'from numbers import Number'; + var functionName = Blockly.Python.provideFunction_( + 'math_mean', + // This operation excludes null and values that aren't int or float:', + // math_mean([null, null, "aString", 1, 9]) == 5.0.', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', + ' localList = [e for e in myList if isinstance(e, Number)]', + ' if not localList: return', + ' return float(sum(localList)) / len(localList)']); + code = functionName + '(' + list + ')'; + break; + case 'MEDIAN': + Blockly.Python.definitions_['from_numbers_import_Number'] = + 'from numbers import Number'; + var functionName = Blockly.Python.provideFunction_( + 'math_median', + // This operation excludes null values: + // math_median([null, null, 1, 3]) == 2.0. + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', + ' localList = sorted([e for e in myList if isinstance(e, Number)])', + ' if not localList: return', + ' if len(localList) % 2 == 0:', + ' return (localList[len(localList) // 2 - 1] + ' + + 'localList[len(localList) // 2]) / 2.0', + ' else:', + ' return localList[(len(localList) - 1) // 2]']); + code = functionName + '(' + list + ')'; + break; + case 'MODE': + var functionName = Blockly.Python.provideFunction_( + 'math_modes', + // As a list of numbers can contain more than one mode, + // the returned result is provided as an array. + // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]. + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(some_list):', + ' modes = []', + ' # Using a lists of [item, count] to keep count rather than dict', + ' # to avoid "unhashable" errors when the counted item is ' + + 'itself a list or dict.', + ' counts = []', + ' maxCount = 1', + ' for item in some_list:', + ' found = False', + ' for count in counts:', + ' if count[0] == item:', + ' count[1] += 1', + ' maxCount = max(maxCount, count[1])', + ' found = True', + ' if not found:', + ' counts.append([item, 1])', + ' for counted_item, item_count in counts:', + ' if item_count == maxCount:', + ' modes.append(counted_item)', + ' return modes']); + code = functionName + '(' + list + ')'; + break; + case 'STD_DEV': + Blockly.Python.definitions_['import_math'] = 'import math'; + var functionName = Blockly.Python.provideFunction_( + 'math_standard_deviation', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(numbers):', + ' n = len(numbers)', + ' if n == 0: return', + ' mean = float(sum(numbers)) / n', + ' variance = sum((x - mean) ** 2 for x in numbers) / n', + ' return math.sqrt(variance)']); + code = functionName + '(' + list + ')'; + break; + case 'RANDOM': + Blockly.Python.definitions_['import_random'] = 'import random'; + code = 'random.choice(' + list + ')'; + break; + default: + throw 'Unknown operator: ' + func; + } + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['math_modulo'] = function(block) { + // Remainder computation. + var argument0 = Blockly.Python.valueToCode(block, 'DIVIDEND', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'DIVISOR', + Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; + var code = argument0 + ' % ' + argument1; + return [code, Blockly.Python.ORDER_MULTIPLICATIVE]; +}; + +Blockly.Python['math_constrain'] = function(block) { + // Constrain a number between two limits. + var argument0 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'LOW', + Blockly.Python.ORDER_NONE) || '0'; + var argument2 = Blockly.Python.valueToCode(block, 'HIGH', + Blockly.Python.ORDER_NONE) || 'float(\'inf\')'; + var code = 'min(max(' + argument0 + ', ' + argument1 + '), ' + + argument2 + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['math_random_int'] = function(block) { + // Random integer between [X] and [Y]. + Blockly.Python.definitions_['import_random'] = 'import random'; + var argument0 = Blockly.Python.valueToCode(block, 'FROM', + Blockly.Python.ORDER_NONE) || '0'; + var argument1 = Blockly.Python.valueToCode(block, 'TO', + Blockly.Python.ORDER_NONE) || '0'; + var code = 'random.randint(' + argument0 + ', ' + argument1 + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['math_random_float'] = function(block) { + // Random fraction between 0 and 1. + Blockly.Python.definitions_['import_random'] = 'import random'; + return ['random.random()', Blockly.Python.ORDER_FUNCTION_CALL]; +}; diff --git a/Blockly/brobot/generators/python/procedures.js b/Blockly/brobot/generators/python/procedures.js new file mode 100644 index 0000000..6af1448 --- /dev/null +++ b/Blockly/brobot/generators/python/procedures.js @@ -0,0 +1,120 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for procedure blocks. + * @author fraser@google.com (Neil Fraser) + */ +'use strict'; + +goog.provide('Blockly.Python.procedures'); + +goog.require('Blockly.Python'); + + +Blockly.Python['procedures_defreturn'] = function(block) { + // Define a procedure with a return value. + // First, add a 'global' statement for every variable that is not shadowed by + // a local parameter. + var globals = []; + for (var i = 0, varName; varName = block.workspace.variableList[i]; i++) { + if (block.arguments_.indexOf(varName) == -1) { + globals.push(Blockly.Python.variableDB_.getName(varName, + Blockly.Variables.NAME_TYPE)); + } + } + globals = globals.length ? ' global ' + globals.join(', ') + '\n' : ''; + var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var branch = Blockly.Python.statementToCode(block, 'STACK'); + if (Blockly.Python.STATEMENT_PREFIX) { + branch = Blockly.Python.prefixLines( + Blockly.Python.STATEMENT_PREFIX.replace(/%1/g, + '\'' + block.id + '\''), Blockly.Python.INDENT) + branch; + } + if (Blockly.Python.INFINITE_LOOP_TRAP) { + branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g, + '"' + block.id + '"') + branch; + } + var returnValue = Blockly.Python.valueToCode(block, 'RETURN', + Blockly.Python.ORDER_NONE) || ''; + if (returnValue) { + returnValue = ' return ' + returnValue + '\n'; + } else if (!branch) { + branch = Blockly.Python.PASS; + } + var args = []; + for (var i = 0; i < block.arguments_.length; i++) { + args[i] = Blockly.Python.variableDB_.getName(block.arguments_[i], + Blockly.Variables.NAME_TYPE); + } + var code = 'def ' + funcName + '(' + args.join(', ') + '):\n' + + globals + branch + returnValue; + code = Blockly.Python.scrub_(block, code); + // Add % so as not to collide with helper functions in definitions list. + Blockly.Python.definitions_['%' + funcName] = code; + return null; +}; + +// Defining a procedure without a return value uses the same generator as +// a procedure with a return value. +Blockly.Python['procedures_defnoreturn'] = + Blockly.Python['procedures_defreturn']; + +Blockly.Python['procedures_callreturn'] = function(block) { + // Call a procedure with a return value. + var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var args = []; + for (var i = 0; i < block.arguments_.length; i++) { + args[i] = Blockly.Python.valueToCode(block, 'ARG' + i, + Blockly.Python.ORDER_NONE) || 'None'; + } + var code = funcName + '(' + args.join(', ') + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['procedures_callnoreturn'] = function(block) { + // Call a procedure with no return value. + var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'), + Blockly.Procedures.NAME_TYPE); + var args = []; + for (var i = 0; i < block.arguments_.length; i++) { + args[i] = Blockly.Python.valueToCode(block, 'ARG' + i, + Blockly.Python.ORDER_NONE) || 'None'; + } + var code = funcName + '(' + args.join(', ') + ')\n'; + return code; +}; + +Blockly.Python['procedures_ifreturn'] = function(block) { + // Conditionally return value from a procedure. + var condition = Blockly.Python.valueToCode(block, 'CONDITION', + Blockly.Python.ORDER_NONE) || 'False'; + var code = 'if ' + condition + ':\n'; + if (block.hasReturnValue_) { + var value = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || 'None'; + code += ' return ' + value + '\n'; + } else { + code += ' return\n'; + } + return code; +}; diff --git a/Blockly/brobot/generators/python/text.js b/Blockly/brobot/generators/python/text.js new file mode 100644 index 0000000..cd6e35d --- /dev/null +++ b/Blockly/brobot/generators/python/text.js @@ -0,0 +1,253 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for text blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.texts'); + +goog.require('Blockly.Python'); + + +Blockly.Python['text'] = function(block) { + // Text value. + var code = Blockly.Python.quote_(block.getFieldValue('TEXT')); + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['text_join'] = function(block) { + // Create a string made up of any number of elements of any type. + //Should we allow joining by '-' or ',' or any other characters? + switch (block.itemCount_) { + case 0: + return ['\'\'', Blockly.Python.ORDER_ATOMIC]; + break; + case 1: + var element = Blockly.Python.valueToCode(block, 'ADD0', + Blockly.Python.ORDER_NONE) || '\'\''; + var code = 'str(' + element + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + break; + case 2: + var element0 = Blockly.Python.valueToCode(block, 'ADD0', + Blockly.Python.ORDER_NONE) || '\'\''; + var element1 = Blockly.Python.valueToCode(block, 'ADD1', + Blockly.Python.ORDER_NONE) || '\'\''; + var code = 'str(' + element0 + ') + str(' + element1 + ')'; + return [code, Blockly.Python.ORDER_ADDITIVE]; + break; + default: + var elements = []; + for (var i = 0; i < block.itemCount_; i++) { + elements[i] = Blockly.Python.valueToCode(block, 'ADD' + i, + Blockly.Python.ORDER_NONE) || '\'\''; + } + var tempVar = Blockly.Python.variableDB_.getDistinctName('x', + Blockly.Variables.NAME_TYPE); + var code = '\'\'.join([str(' + tempVar + ') for ' + tempVar + ' in [' + + elements.join(', ') + ']])'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } +}; + +Blockly.Python['text_append'] = function(block) { + // Append to a variable in place. + var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + var value = Blockly.Python.valueToCode(block, 'TEXT', + Blockly.Python.ORDER_NONE) || '\'\''; + return varName + ' = str(' + varName + ') + str(' + value + ')\n'; +}; + +Blockly.Python['text_length'] = function(block) { + // Is the string null or array empty? + var text = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '\'\''; + return ['len(' + text + ')', Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['text_isEmpty'] = function(block) { + // Is the string null or array empty? + var text = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '\'\''; + var code = 'not len(' + text + ')'; + return [code, Blockly.Python.ORDER_LOGICAL_NOT]; +}; + +Blockly.Python['text_indexOf'] = function(block) { + // Search the text for a substring. + // Should we allow for non-case sensitive??? + var operator = block.getFieldValue('END') == 'FIRST' ? 'find' : 'rfind'; + var substring = Blockly.Python.valueToCode(block, 'FIND', + Blockly.Python.ORDER_NONE) || '\'\''; + var text = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var code = text + '.' + operator + '(' + substring + ')'; + if (block.workspace.options.oneBasedIndex) { + return [code + ' + 1', Blockly.Python.ORDER_ADDITIVE]; + } + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['text_charAt'] = function(block) { + // Get letter at index. + // Note: Until January 2013 this block did not have the WHERE input. + var where = block.getFieldValue('WHERE') || 'FROM_START'; + var text = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_MEMBER) || '\'\''; + switch (where) { + case 'FIRST': + var code = text + '[0]'; + return [code, Blockly.Python.ORDER_MEMBER]; + case 'LAST': + var code = text + '[-1]'; + return [code, Blockly.Python.ORDER_MEMBER]; + case 'FROM_START': + var at = Blockly.Python.getAdjustedInt(block, 'AT'); + var code = text + '[' + at + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; + case 'FROM_END': + var at = Blockly.Python.getAdjustedInt(block, 'AT', 1, true); + var code = text + '[' + at + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; + case 'RANDOM': + Blockly.Python.definitions_['import_random'] = 'import random'; + var functionName = Blockly.Python.provideFunction_( + 'text_random_letter', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(text):', + ' x = int(random.random() * len(text))', + ' return text[x];']); + code = functionName + '(' + text + ')'; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; + } + throw 'Unhandled option (text_charAt).'; +}; + +Blockly.Python['text_getSubstring'] = function(block) { + // Get substring. + var where1 = block.getFieldValue('WHERE1'); + var where2 = block.getFieldValue('WHERE2'); + var text = Blockly.Python.valueToCode(block, 'STRING', + Blockly.Python.ORDER_MEMBER) || '\'\''; + switch (where1) { + case 'FROM_START': + var at1 = Blockly.Python.getAdjustedInt(block, 'AT1'); + if (at1 == '0') { + at1 = ''; + } + break; + case 'FROM_END': + var at1 = Blockly.Python.getAdjustedInt(block, 'AT1', 1, true); + break; + case 'FIRST': + var at1 = ''; + break; + default: + throw 'Unhandled option (text_getSubstring)'; + } + switch (where2) { + case 'FROM_START': + var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 1); + break; + case 'FROM_END': + var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 0, true); + // Ensure that if the result calculated is 0 that sub-sequence will + // include all elements as expected. + if (!Blockly.isNumber(String(at2))) { + Blockly.Python.definitions_['import_sys'] = 'import sys'; + at2 += ' or sys.maxsize'; + } else if (at2 == '0') { + at2 = ''; + } + break; + case 'LAST': + var at2 = ''; + break; + default: + throw 'Unhandled option (text_getSubstring)'; + } + var code = text + '[' + at1 + ' : ' + at2 + ']'; + return [code, Blockly.Python.ORDER_MEMBER]; +}; + +Blockly.Python['text_changeCase'] = function(block) { + // Change capitalization. + var OPERATORS = { + 'UPPERCASE': '.upper()', + 'LOWERCASE': '.lower()', + 'TITLECASE': '.title()' + }; + var operator = OPERATORS[block.getFieldValue('CASE')]; + var text = Blockly.Python.valueToCode(block, 'TEXT', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var code = text + operator; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['text_trim'] = function(block) { + // Trim spaces. + var OPERATORS = { + 'LEFT': '.lstrip()', + 'RIGHT': '.rstrip()', + 'BOTH': '.strip()' + }; + var operator = OPERATORS[block.getFieldValue('MODE')]; + var text = Blockly.Python.valueToCode(block, 'TEXT', + Blockly.Python.ORDER_MEMBER) || '\'\''; + var code = text + operator; + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['text_print'] = function(block) { + // Print statement. + var msg = Blockly.Python.valueToCode(block, 'TEXT', + Blockly.Python.ORDER_NONE) || '\'\''; + return 'print(' + msg + ')\n'; +}; + +Blockly.Python['text_prompt_ext'] = function(block) { + // Prompt function. + var functionName = Blockly.Python.provideFunction_( + 'text_prompt', + ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(msg):', + ' try:', + ' return raw_input(msg)', + ' except NameError:', + ' return input(msg)']); + if (block.getField('TEXT')) { + // Internal message. + var msg = Blockly.Python.quote_(block.getFieldValue('TEXT')); + } else { + // External message. + var msg = Blockly.Python.valueToCode(block, 'TEXT', + Blockly.Python.ORDER_NONE) || '\'\''; + } + var code = functionName + '(' + msg + ')'; + var toNumber = block.getFieldValue('TYPE') == 'NUMBER'; + if (toNumber) { + code = 'float(' + code + ')'; + } + return [code, Blockly.Python.ORDER_FUNCTION_CALL]; +}; + +Blockly.Python['text_prompt'] = Blockly.Python['text_prompt_ext']; diff --git a/Blockly/brobot/generators/python/variables.js b/Blockly/brobot/generators/python/variables.js new file mode 100644 index 0000000..00d9971 --- /dev/null +++ b/Blockly/brobot/generators/python/variables.js @@ -0,0 +1,46 @@ +/** + * @license + * Visual Blocks Language + * + * Copyright 2012 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Generating Python for variable blocks. + * @author q.neutron@gmail.com (Quynh Neutron) + */ +'use strict'; + +goog.provide('Blockly.Python.variables'); + +goog.require('Blockly.Python'); + + +Blockly.Python['variables_get'] = function(block) { + // Variable getter. + var code = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + return [code, Blockly.Python.ORDER_ATOMIC]; +}; + +Blockly.Python['variables_set'] = function(block) { + // Variable setter. + var argument0 = Blockly.Python.valueToCode(block, 'VALUE', + Blockly.Python.ORDER_NONE) || '0'; + var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), + Blockly.Variables.NAME_TYPE); + return varName + ' = ' + argument0 + '\n'; +}; diff --git a/Blockly/brobot/icons.png b/Blockly/brobot/icons.png new file mode 100644 index 0000000..7cced7a Binary files /dev/null and b/Blockly/brobot/icons.png differ diff --git a/Blockly/brobot/index.html b/Blockly/brobot/index.html new file mode 100644 index 0000000..02cfa12 --- /dev/null +++ b/Blockly/brobot/index.html @@ -0,0 +1,216 @@ + + + + + + BROBOT Block programming + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +

BROBOT Block Programming v0.8

+ + +
+ + + + + + + + + + + +
... JavaScript Python XML + + + +
+
+
+
+

+  

+  
+
+  
+
+  
+

Remember to connect your PC/laptop to to your B-Robot Wifi network! (JJROBOTS_xx, password:87654321)

+
+ + + diff --git a/Blockly/brobot/javascript_compressed.js b/Blockly/brobot/javascript_compressed.js new file mode 100644 index 0000000..5507d7e --- /dev/null +++ b/Blockly/brobot/javascript_compressed.js @@ -0,0 +1,91 @@ +// Do not edit this file; automatically generated by build.py. +'use strict'; + + +// Copyright 2012 Google Inc. Apache License 2.0 +Blockly.JavaScript=new Blockly.Generator("JavaScript");Blockly.JavaScript.addReservedWords("Blockly,break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,class,enum,export,extends,import,super,implements,interface,let,package,private,protected,public,static,yield,const,null,true,false,Array,ArrayBuffer,Boolean,Date,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Error,eval,EvalError,Float32Array,Float64Array,Function,Infinity,Int16Array,Int32Array,Int8Array,isFinite,isNaN,Iterator,JSON,Math,NaN,Number,Object,parseFloat,parseInt,RangeError,ReferenceError,RegExp,StopIteration,String,SyntaxError,TypeError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,undefined,uneval,URIError,applicationCache,closed,Components,content,_content,controllers,crypto,defaultStatus,dialogArguments,directories,document,frameElement,frames,fullScreen,globalStorage,history,innerHeight,innerWidth,length,location,locationbar,localStorage,menubar,messageManager,mozAnimationStartTime,mozInnerScreenX,mozInnerScreenY,mozPaintCount,name,navigator,opener,outerHeight,outerWidth,pageXOffset,pageYOffset,parent,performance,personalbar,pkcs11,returnValue,screen,screenX,screenY,scrollbars,scrollMaxX,scrollMaxY,scrollX,scrollY,self,sessionStorage,sidebar,status,statusbar,toolbar,top,URL,window,addEventListener,alert,atob,back,blur,btoa,captureEvents,clearImmediate,clearInterval,clearTimeout,close,confirm,disableExternalCapture,dispatchEvent,dump,enableExternalCapture,escape,find,focus,forward,GeckoActiveXObject,getAttention,getAttentionWithCycleCount,getComputedStyle,getSelection,home,matchMedia,maximize,minimize,moveBy,moveTo,mozRequestAnimationFrame,open,openDialog,postMessage,print,prompt,QueryInterface,releaseEvents,removeEventListener,resizeBy,resizeTo,restore,routeEvent,scroll,scrollBy,scrollByLines,scrollByPages,scrollTo,setCursor,setImmediate,setInterval,setResizable,setTimeout,showModalDialog,sizeToContent,stop,unescape,updateCommands,XPCNativeWrapper,XPCSafeJSObjectWrapper,onabort,onbeforeunload,onblur,onchange,onclick,onclose,oncontextmenu,ondevicemotion,ondeviceorientation,ondragdrop,onerror,onfocus,onhashchange,onkeydown,onkeypress,onkeyup,onload,onmousedown,onmousemove,onmouseout,onmouseover,onmouseup,onmozbeforepaint,onpaint,onpopstate,onreset,onresize,onscroll,onselect,onsubmit,onunload,onpageshow,onpagehide,Image,Option,Worker,Event,Range,File,FileReader,Blob,BlobBuilder,Attr,CDATASection,CharacterData,Comment,console,DocumentFragment,DocumentType,DomConfiguration,DOMError,DOMErrorHandler,DOMException,DOMImplementation,DOMImplementationList,DOMImplementationRegistry,DOMImplementationSource,DOMLocator,DOMObject,DOMString,DOMStringList,DOMTimeStamp,DOMUserData,Entity,EntityReference,MediaQueryList,MediaQueryListListener,NameList,NamedNodeMap,Node,NodeFilter,NodeIterator,NodeList,Notation,Plugin,PluginArray,ProcessingInstruction,SharedWorker,Text,TimeRanges,Treewalker,TypeInfo,UserDataHandler,Worker,WorkerGlobalScope,HTMLDocument,HTMLElement,HTMLAnchorElement,HTMLAppletElement,HTMLAudioElement,HTMLAreaElement,HTMLBaseElement,HTMLBaseFontElement,HTMLBodyElement,HTMLBRElement,HTMLButtonElement,HTMLCanvasElement,HTMLDirectoryElement,HTMLDivElement,HTMLDListElement,HTMLEmbedElement,HTMLFieldSetElement,HTMLFontElement,HTMLFormElement,HTMLFrameElement,HTMLFrameSetElement,HTMLHeadElement,HTMLHeadingElement,HTMLHtmlElement,HTMLHRElement,HTMLIFrameElement,HTMLImageElement,HTMLInputElement,HTMLKeygenElement,HTMLLabelElement,HTMLLIElement,HTMLLinkElement,HTMLMapElement,HTMLMenuElement,HTMLMetaElement,HTMLModElement,HTMLObjectElement,HTMLOListElement,HTMLOptGroupElement,HTMLOptionElement,HTMLOutputElement,HTMLParagraphElement,HTMLParamElement,HTMLPreElement,HTMLQuoteElement,HTMLScriptElement,HTMLSelectElement,HTMLSourceElement,HTMLSpanElement,HTMLStyleElement,HTMLTableElement,HTMLTableCaptionElement,HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement,HTMLTableColElement,HTMLTableRowElement,HTMLTableSectionElement,HTMLTextAreaElement,HTMLTimeElement,HTMLTitleElement,HTMLTrackElement,HTMLUListElement,HTMLUnknownElement,HTMLVideoElement,HTMLCanvasElement,CanvasRenderingContext2D,CanvasGradient,CanvasPattern,TextMetrics,ImageData,CanvasPixelArray,HTMLAudioElement,HTMLVideoElement,NotifyAudioAvailableEvent,HTMLCollection,HTMLAllCollection,HTMLFormControlsCollection,HTMLOptionsCollection,HTMLPropertiesCollection,DOMTokenList,DOMSettableTokenList,DOMStringMap,RadioNodeList,SVGDocument,SVGElement,SVGAElement,SVGAltGlyphElement,SVGAltGlyphDefElement,SVGAltGlyphItemElement,SVGAnimationElement,SVGAnimateElement,SVGAnimateColorElement,SVGAnimateMotionElement,SVGAnimateTransformElement,SVGSetElement,SVGCircleElement,SVGClipPathElement,SVGColorProfileElement,SVGCursorElement,SVGDefsElement,SVGDescElement,SVGEllipseElement,SVGFilterElement,SVGFilterPrimitiveStandardAttributes,SVGFEBlendElement,SVGFEColorMatrixElement,SVGFEComponentTransferElement,SVGFECompositeElement,SVGFEConvolveMatrixElement,SVGFEDiffuseLightingElement,SVGFEDisplacementMapElement,SVGFEDistantLightElement,SVGFEFloodElement,SVGFEGaussianBlurElement,SVGFEImageElement,SVGFEMergeElement,SVGFEMergeNodeElement,SVGFEMorphologyElement,SVGFEOffsetElement,SVGFEPointLightElement,SVGFESpecularLightingElement,SVGFESpotLightElement,SVGFETileElement,SVGFETurbulenceElement,SVGComponentTransferFunctionElement,SVGFEFuncRElement,SVGFEFuncGElement,SVGFEFuncBElement,SVGFEFuncAElement,SVGFontElement,SVGFontFaceElement,SVGFontFaceFormatElement,SVGFontFaceNameElement,SVGFontFaceSrcElement,SVGFontFaceUriElement,SVGForeignObjectElement,SVGGElement,SVGGlyphElement,SVGGlyphRefElement,SVGGradientElement,SVGLinearGradientElement,SVGRadialGradientElement,SVGHKernElement,SVGImageElement,SVGLineElement,SVGMarkerElement,SVGMaskElement,SVGMetadataElement,SVGMissingGlyphElement,SVGMPathElement,SVGPathElement,SVGPatternElement,SVGPolylineElement,SVGPolygonElement,SVGRectElement,SVGScriptElement,SVGStopElement,SVGStyleElement,SVGSVGElement,SVGSwitchElement,SVGSymbolElement,SVGTextElement,SVGTextPathElement,SVGTitleElement,SVGTRefElement,SVGTSpanElement,SVGUseElement,SVGViewElement,SVGVKernElement,SVGAngle,SVGColor,SVGICCColor,SVGElementInstance,SVGElementInstanceList,SVGLength,SVGLengthList,SVGMatrix,SVGNumber,SVGNumberList,SVGPaint,SVGPoint,SVGPointList,SVGPreserveAspectRatio,SVGRect,SVGStringList,SVGTransform,SVGTransformList,SVGAnimatedAngle,SVGAnimatedBoolean,SVGAnimatedEnumeration,SVGAnimatedInteger,SVGAnimatedLength,SVGAnimatedLengthList,SVGAnimatedNumber,SVGAnimatedNumberList,SVGAnimatedPreserveAspectRatio,SVGAnimatedRect,SVGAnimatedString,SVGAnimatedTransformList,SVGPathSegList,SVGPathSeg,SVGPathSegArcAbs,SVGPathSegArcRel,SVGPathSegClosePath,SVGPathSegCurvetoCubicAbs,SVGPathSegCurvetoCubicRel,SVGPathSegCurvetoCubicSmoothAbs,SVGPathSegCurvetoCubicSmoothRel,SVGPathSegCurvetoQuadraticAbs,SVGPathSegCurvetoQuadraticRel,SVGPathSegCurvetoQuadraticSmoothAbs,SVGPathSegCurvetoQuadraticSmoothRel,SVGPathSegLinetoAbs,SVGPathSegLinetoHorizontalAbs,SVGPathSegLinetoHorizontalRel,SVGPathSegLinetoRel,SVGPathSegLinetoVerticalAbs,SVGPathSegLinetoVerticalRel,SVGPathSegMovetoAbs,SVGPathSegMovetoRel,ElementTimeControl,TimeEvent,SVGAnimatedPathData,SVGAnimatedPoints,SVGColorProfileRule,SVGCSSRule,SVGExternalResourcesRequired,SVGFitToViewBox,SVGLangSpace,SVGLocatable,SVGRenderingIntent,SVGStylable,SVGTests,SVGTextContentElement,SVGTextPositioningElement,SVGTransformable,SVGUnitTypes,SVGURIReference,SVGViewSpec,SVGZoomAndPan"); +Blockly.JavaScript.ORDER_ATOMIC=0;Blockly.JavaScript.ORDER_NEW=1.1;Blockly.JavaScript.ORDER_MEMBER=1.2;Blockly.JavaScript.ORDER_FUNCTION_CALL=2;Blockly.JavaScript.ORDER_INCREMENT=3;Blockly.JavaScript.ORDER_DECREMENT=3;Blockly.JavaScript.ORDER_BITWISE_NOT=4.1;Blockly.JavaScript.ORDER_UNARY_PLUS=4.2;Blockly.JavaScript.ORDER_UNARY_NEGATION=4.3;Blockly.JavaScript.ORDER_LOGICAL_NOT=4.4;Blockly.JavaScript.ORDER_TYPEOF=4.5;Blockly.JavaScript.ORDER_VOID=4.6;Blockly.JavaScript.ORDER_DELETE=4.7; +Blockly.JavaScript.ORDER_DIVISION=5.1;Blockly.JavaScript.ORDER_MULTIPLICATION=5.2;Blockly.JavaScript.ORDER_MODULUS=5.3;Blockly.JavaScript.ORDER_SUBTRACTION=6.1;Blockly.JavaScript.ORDER_ADDITION=6.2;Blockly.JavaScript.ORDER_BITWISE_SHIFT=7;Blockly.JavaScript.ORDER_RELATIONAL=8;Blockly.JavaScript.ORDER_IN=8;Blockly.JavaScript.ORDER_INSTANCEOF=8;Blockly.JavaScript.ORDER_EQUALITY=9;Blockly.JavaScript.ORDER_BITWISE_AND=10;Blockly.JavaScript.ORDER_BITWISE_XOR=11;Blockly.JavaScript.ORDER_BITWISE_OR=12; +Blockly.JavaScript.ORDER_LOGICAL_AND=13;Blockly.JavaScript.ORDER_LOGICAL_OR=14;Blockly.JavaScript.ORDER_CONDITIONAL=15;Blockly.JavaScript.ORDER_ASSIGNMENT=16;Blockly.JavaScript.ORDER_COMMA=17;Blockly.JavaScript.ORDER_NONE=99; +Blockly.JavaScript.ORDER_OVERRIDES=[[Blockly.JavaScript.ORDER_FUNCTION_CALL,Blockly.JavaScript.ORDER_MEMBER],[Blockly.JavaScript.ORDER_FUNCTION_CALL,Blockly.JavaScript.ORDER_FUNCTION_CALL],[Blockly.JavaScript.ORDER_MEMBER,Blockly.JavaScript.ORDER_MEMBER],[Blockly.JavaScript.ORDER_MEMBER,Blockly.JavaScript.ORDER_FUNCTION_CALL],[Blockly.JavaScript.ORDER_LOGICAL_NOT,Blockly.JavaScript.ORDER_LOGICAL_NOT],[Blockly.JavaScript.ORDER_MULTIPLICATION,Blockly.JavaScript.ORDER_MULTIPLICATION],[Blockly.JavaScript.ORDER_ADDITION, +Blockly.JavaScript.ORDER_ADDITION],[Blockly.JavaScript.ORDER_LOGICAL_AND,Blockly.JavaScript.ORDER_LOGICAL_AND],[Blockly.JavaScript.ORDER_LOGICAL_OR,Blockly.JavaScript.ORDER_LOGICAL_OR]]; +Blockly.JavaScript.init=function(a){Blockly.JavaScript.definitions_=Object.create(null);Blockly.JavaScript.functionNames_=Object.create(null);Blockly.JavaScript.variableDB_?Blockly.JavaScript.variableDB_.reset():Blockly.JavaScript.variableDB_=new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_);var b=[];a=a.variableList;if(a.length){for(var c=0;cc?Blockly.JavaScript.valueToCode(a,b,Blockly.JavaScript.ORDER_SUBTRACTION)||f:d?Blockly.JavaScript.valueToCode(a,b,Blockly.JavaScript.ORDER_UNARY_NEGATION)||f:Blockly.JavaScript.valueToCode(a,b,e)||f;if(Blockly.isNumber(a))a=parseFloat(a)+c, +d&&(a=-a);else{if(0c&&(a=a+" - "+-c,g=Blockly.JavaScript.ORDER_SUBTRACTION);d&&(a=c?"-("+a+")":"-"+a,g=Blockly.JavaScript.ORDER_UNARY_NEGATION);g=Math.floor(g);e=Math.floor(e);g&&e>=g&&(a="("+a+")")}return a};Blockly.JavaScript.lists={};Blockly.JavaScript.lists_create_empty=function(a){return["[]",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c b.toString() ? 1 : -1; },", +' "IGNORE_CASE": function(a, b) {'," return a.toString().toLowerCase() > b.toString().toLowerCase() ? 1 : -1; },"," };"," var compare = compareFuncs[type];"," return function(a, b) { return compare(a, b) * direction; }","}"]);return[b+".slice().sort("+d+'("'+a+'", '+c+"))",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.lists_split=function(a){var b=Blockly.JavaScript.valueToCode(a,"INPUT",Blockly.JavaScript.ORDER_MEMBER),c=Blockly.JavaScript.valueToCode(a,"DELIM",Blockly.JavaScript.ORDER_NONE)||"''";a=a.getFieldValue("MODE");if("SPLIT"==a)b||(b="''"),a="split";else if("JOIN"==a)b||(b="[]"),a="join";else throw"Unknown mode: "+a;return[b+"."+a+"("+c+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math={};Blockly.JavaScript.math_number=function(a){return[parseFloat(a.getFieldValue("NUM")),Blockly.JavaScript.ORDER_ATOMIC]}; +Blockly.JavaScript.math_arithmetic=function(a){var b={ADD:[" + ",Blockly.JavaScript.ORDER_ADDITION],MINUS:[" - ",Blockly.JavaScript.ORDER_SUBTRACTION],MULTIPLY:[" * ",Blockly.JavaScript.ORDER_MULTIPLICATION],DIVIDE:[" / ",Blockly.JavaScript.ORDER_DIVISION],POWER:[null,Blockly.JavaScript.ORDER_COMMA]}[a.getFieldValue("OP")],c=b[0],b=b[1],d=Blockly.JavaScript.valueToCode(a,"A",b)||"0";a=Blockly.JavaScript.valueToCode(a,"B",b)||"0";return c?[d+c+a,b]:["Math.pow("+d+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.math_single=function(a){var b=a.getFieldValue("OP"),c;if("NEG"==b)return a=Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_UNARY_NEGATION)||"0","-"==a[0]&&(a=" "+a),["-"+a,Blockly.JavaScript.ORDER_UNARY_NEGATION];a="SIN"==b||"COS"==b||"TAN"==b?Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_DIVISION)||"0":Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_NONE)||"0";switch(b){case "ABS":c="Math.abs("+a+")";break;case "ROOT":c="Math.sqrt("+ +a+")";break;case "LN":c="Math.log("+a+")";break;case "EXP":c="Math.exp("+a+")";break;case "POW10":c="Math.pow(10,"+a+")";break;case "ROUND":c="Math.round("+a+")";break;case "ROUNDUP":c="Math.ceil("+a+")";break;case "ROUNDDOWN":c="Math.floor("+a+")";break;case "SIN":c="Math.sin("+a+" / 180 * Math.PI)";break;case "COS":c="Math.cos("+a+" / 180 * Math.PI)";break;case "TAN":c="Math.tan("+a+" / 180 * Math.PI)"}if(c)return[c,Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(b){case "LOG10":c="Math.log("+a+ +") / Math.log(10)";break;case "ASIN":c="Math.asin("+a+") / Math.PI * 180";break;case "ACOS":c="Math.acos("+a+") / Math.PI * 180";break;case "ATAN":c="Math.atan("+a+") / Math.PI * 180";break;default:throw"Unknown math operator: "+b;}return[c,Blockly.JavaScript.ORDER_DIVISION]}; +Blockly.JavaScript.math_constant=function(a){return{PI:["Math.PI",Blockly.JavaScript.ORDER_MEMBER],E:["Math.E",Blockly.JavaScript.ORDER_MEMBER],GOLDEN_RATIO:["(1 + Math.sqrt(5)) / 2",Blockly.JavaScript.ORDER_DIVISION],SQRT2:["Math.SQRT2",Blockly.JavaScript.ORDER_MEMBER],SQRT1_2:["Math.SQRT1_2",Blockly.JavaScript.ORDER_MEMBER],INFINITY:["Infinity",Blockly.JavaScript.ORDER_ATOMIC]}[a.getFieldValue("CONSTANT")]}; +Blockly.JavaScript.math_number_property=function(a){var b=Blockly.JavaScript.valueToCode(a,"NUMBER_TO_CHECK",Blockly.JavaScript.ORDER_MODULUS)||"0",c=a.getFieldValue("PROPERTY"),d;if("PRIME"==c)return[Blockly.JavaScript.provideFunction_("mathIsPrime",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(n) {"," // https://en.wikipedia.org/wiki/Primality_test#Naive_methods"," if (n == 2 || n == 3) {"," return true;"," }"," // False if n is NaN, negative, is 1, or not whole."," // And false if n is divisible by 2 or 3.", +" if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 || n % 3 == 0) {"," return false;"," }"," // Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {"," if (n % (x - 1) == 0 || n % (x + 1) == 0) {"," return false;"," }"," }"," return true;","}"])+"("+b+")",Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(c){case "EVEN":d=b+" % 2 == 0";break;case "ODD":d=b+" % 2 == 1";break;case "WHOLE":d=b+" % 1 == 0";break;case "POSITIVE":d= +b+" > 0";break;case "NEGATIVE":d=b+" < 0";break;case "DIVISIBLE_BY":a=Blockly.JavaScript.valueToCode(a,"DIVISOR",Blockly.JavaScript.ORDER_MODULUS)||"0",d=b+" % "+a+" == 0"}return[d,Blockly.JavaScript.ORDER_EQUALITY]};Blockly.JavaScript.math_change=function(a){var b=Blockly.JavaScript.valueToCode(a,"DELTA",Blockly.JavaScript.ORDER_ADDITION)||"0";a=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE);return a+" = (typeof "+a+" == 'number' ? "+a+" : 0) + "+b+";\n"}; +Blockly.JavaScript.math_round=Blockly.JavaScript.math_single;Blockly.JavaScript.math_trig=Blockly.JavaScript.math_single; +Blockly.JavaScript.math_on_list=function(a){var b=a.getFieldValue("OP");switch(b){case "SUM":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_MEMBER)||"[]";a+=".reduce(function(x, y) {return x + y;})";break;case "MIN":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_COMMA)||"[]";a="Math.min.apply(null, "+a+")";break;case "MAX":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_COMMA)||"[]";a="Math.max.apply(null, "+a+")";break;case "AVERAGE":b=Blockly.JavaScript.provideFunction_("mathMean", +["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," return myList.reduce(function(x, y) {return x + y;}) / myList.length;","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "MEDIAN":b=Blockly.JavaScript.provideFunction_("mathMedian",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," var localList = myList.filter(function (x) {return typeof x == 'number';});"," if (!localList.length) return null;", +" localList.sort(function(a, b) {return b - a;});"," if (localList.length % 2 == 0) {"," return (localList[localList.length / 2 - 1] + localList[localList.length / 2]) / 2;"," } else {"," return localList[(localList.length - 1) / 2];"," }","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "MODE":b=Blockly.JavaScript.provideFunction_("mathModes",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(values) {"," var modes = [];", +" var counts = [];"," var maxCount = 0;"," for (var i = 0; i < values.length; i++) {"," var value = values[i];"," var found = false;"," var thisCount;"," for (var j = 0; j < counts.length; j++) {"," if (counts[j][0] === value) {"," thisCount = ++counts[j][1];"," found = true;"," break;"," }"," }"," if (!found) {"," counts.push([value, 1]);"," thisCount = 1;"," }"," maxCount = Math.max(thisCount, maxCount);"," }"," for (var j = 0; j < counts.length; j++) {", +" if (counts[j][1] == maxCount) {"," modes.push(counts[j][0]);"," }"," }"," return modes;","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "STD_DEV":b=Blockly.JavaScript.provideFunction_("mathStandardDeviation",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(numbers) {"," var n = numbers.length;"," if (!n) return null;"," var mean = numbers.reduce(function(x, y) {return x + y;}) / n;"," var variance = 0;", +" for (var j = 0; j < n; j++) {"," variance += Math.pow(numbers[j] - mean, 2);"," }"," variance = variance / n;"," return Math.sqrt(variance);","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "RANDOM":b=Blockly.JavaScript.provideFunction_("mathRandomList",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(list) {"," var x = Math.floor(Math.random() * list.length);"," return list[x];","}"]);a=Blockly.JavaScript.valueToCode(a, +"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;default:throw"Unknown operator: "+b;}return[a,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_modulo=function(a){var b=Blockly.JavaScript.valueToCode(a,"DIVIDEND",Blockly.JavaScript.ORDER_MODULUS)||"0";a=Blockly.JavaScript.valueToCode(a,"DIVISOR",Blockly.JavaScript.ORDER_MODULUS)||"0";return[b+" % "+a,Blockly.JavaScript.ORDER_MODULUS]}; +Blockly.JavaScript.math_constrain=function(a){var b=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_COMMA)||"0",c=Blockly.JavaScript.valueToCode(a,"LOW",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"HIGH",Blockly.JavaScript.ORDER_COMMA)||"Infinity";return["Math.min(Math.max("+b+", "+c+"), "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.math_random_int=function(a){var b=Blockly.JavaScript.valueToCode(a,"FROM",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"TO",Blockly.JavaScript.ORDER_COMMA)||"0";return[Blockly.JavaScript.provideFunction_("mathRandomInt",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(a, b) {"," if (a > b) {"," // Swap a and b to ensure a is smaller."," var c = a;"," a = b;"," b = c;"," }"," return Math.floor(Math.random() * (b - a + 1) + a);", +"}"])+"("+b+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_random_float=function(a){return["Math.random()",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.variables={};Blockly.JavaScript.variables_get=function(a){return[Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.variables_set=function(a){var b=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0";return Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE)+" = "+b+";\n"};Blockly.JavaScript.colour={};Blockly.JavaScript.colour_picker=function(a){return["'"+a.getFieldValue("COLOUR")+"'",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.colour_random=function(a){return[Blockly.JavaScript.provideFunction_("colourRandom",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"() {"," var num = Math.floor(Math.random() * Math.pow(2, 24));"," return '#' + ('00000' + num.toString(16)).substr(-6);","}"])+"()",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.colour_rgb=function(a){var b=Blockly.JavaScript.valueToCode(a,"RED",Blockly.JavaScript.ORDER_COMMA)||0,c=Blockly.JavaScript.valueToCode(a,"GREEN",Blockly.JavaScript.ORDER_COMMA)||0;a=Blockly.JavaScript.valueToCode(a,"BLUE",Blockly.JavaScript.ORDER_COMMA)||0;return[Blockly.JavaScript.provideFunction_("colourRgb",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(r, g, b) {"," r = Math.max(Math.min(Number(r), 100), 0) * 2.55;"," g = Math.max(Math.min(Number(g), 100), 0) * 2.55;", +" b = Math.max(Math.min(Number(b), 100), 0) * 2.55;"," r = ('0' + (Math.round(r) || 0).toString(16)).slice(-2);"," g = ('0' + (Math.round(g) || 0).toString(16)).slice(-2);"," b = ('0' + (Math.round(b) || 0).toString(16)).slice(-2);"," return '#' + r + g + b;","}"])+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; +Blockly.JavaScript.colour_blend=function(a){var b=Blockly.JavaScript.valueToCode(a,"COLOUR1",Blockly.JavaScript.ORDER_COMMA)||"'#000000'",c=Blockly.JavaScript.valueToCode(a,"COLOUR2",Blockly.JavaScript.ORDER_COMMA)||"'#000000'";a=Blockly.JavaScript.valueToCode(a,"RATIO",Blockly.JavaScript.ORDER_COMMA)||.5;return[Blockly.JavaScript.provideFunction_("colourBlend",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(c1, c2, ratio) {"," ratio = Math.max(Math.min(Number(ratio), 1), 0);"," var r1 = parseInt(c1.substring(1, 3), 16);", +" var g1 = parseInt(c1.substring(3, 5), 16);"," var b1 = parseInt(c1.substring(5, 7), 16);"," var r2 = parseInt(c2.substring(1, 3), 16);"," var g2 = parseInt(c2.substring(3, 5), 16);"," var b2 = parseInt(c2.substring(5, 7), 16);"," var r = Math.round(r1 * (1 - ratio) + r2 * ratio);"," var g = Math.round(g1 * (1 - ratio) + g2 * ratio);"," var b = Math.round(b1 * (1 - ratio) + b2 * ratio);"," r = ('0' + (r || 0).toString(16)).slice(-2);"," g = ('0' + (g || 0).toString(16)).slice(-2);"," b = ('0' + (b || 0).toString(16)).slice(-2);", +" return '#' + r + g + b;","}"])+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.procedures={}; +Blockly.JavaScript.procedures_defreturn=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("NAME"),Blockly.Procedures.NAME_TYPE),c=Blockly.JavaScript.statementToCode(a,"STACK");Blockly.JavaScript.STATEMENT_PREFIX&&(c=Blockly.JavaScript.prefixLines(Blockly.JavaScript.STATEMENT_PREFIX.replace(/%1/g,"'"+a.id+"'"),Blockly.JavaScript.INDENT)+c);Blockly.JavaScript.INFINITE_LOOP_TRAP&&(c=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,"'"+a.id+"'")+c);var d=Blockly.JavaScript.valueToCode(a, +"RETURN",Blockly.JavaScript.ORDER_NONE)||"";d&&(d=" return "+d+";\n");for(var e=[],f=0;f= ")+d+"; "+b;b=Math.abs(parseFloat(e));a=(1==b?a+(g?"++":"--"):a+((g?" += ":" -= ")+b))+(") {\n"+f+"}\n")}else a="",g=c,c.match(/^\w+$/)||Blockly.isNumber(c)||(g=Blockly.JavaScript.variableDB_.getDistinctName(b+"_start",Blockly.Variables.NAME_TYPE),a+="var "+g+" = "+c+";\n"),c=d,d.match(/^\w+$/)||Blockly.isNumber(d)||(c=Blockly.JavaScript.variableDB_.getDistinctName(b+"_end",Blockly.Variables.NAME_TYPE), +a+="var "+c+" = "+d+";\n"),d=Blockly.JavaScript.variableDB_.getDistinctName(b+"_inc",Blockly.Variables.NAME_TYPE),a+="var "+d+" = ",a=Blockly.isNumber(e)?a+(Math.abs(e)+";\n"):a+("Math.abs("+e+");\n"),a=a+("if ("+g+" > "+c+") {\n")+(Blockly.JavaScript.INDENT+d+" = -"+d+";\n"),a+="}\n",a+="for ("+b+" = "+g+"; "+d+" >= 0 ? "+b+" <= "+c+" : "+b+" >= "+c+"; "+b+" += "+d+") {\n"+f+"}\n";return a}; +Blockly.JavaScript.controls_forEach=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_ASSIGNMENT)||"[]",d=Blockly.JavaScript.statementToCode(a,"DO"),d=Blockly.JavaScript.addLoopTrap(d,a.id);a="";var e=c;c.match(/^\w+$/)||(e=Blockly.JavaScript.variableDB_.getDistinctName(b+"_list",Blockly.Variables.NAME_TYPE),a+="var "+e+" = "+c+";\n");c=Blockly.JavaScript.variableDB_.getDistinctName(b+ +"_index",Blockly.Variables.NAME_TYPE);d=Blockly.JavaScript.INDENT+b+" = "+e+"["+c+"];\n"+d;return a+("for (var "+c+" in "+e+") {\n"+d+"}\n")};Blockly.JavaScript.controls_flow_statements=function(a){switch(a.getFieldValue("FLOW")){case "BREAK":return"break;\n";case "CONTINUE":return"continue;\n"}throw"Unknown flow statement.";};Blockly.JavaScript.logic={}; +Blockly.JavaScript.controls_if=function(a){for(var b=0,c=Blockly.JavaScript.valueToCode(a,"IF"+b,Blockly.JavaScript.ORDER_NONE)||"false",d=Blockly.JavaScript.statementToCode(a,"DO"+b),e="if ("+c+") {\n"+d+"}",b=1;b<=a.elseifCount_;b++)c=Blockly.JavaScript.valueToCode(a,"IF"+b,Blockly.JavaScript.ORDER_NONE)||"false",d=Blockly.JavaScript.statementToCode(a,"DO"+b),e+=" else if ("+c+") {\n"+d+"}";a.elseCount_&&(d=Blockly.JavaScript.statementToCode(a,"ELSE"),e+=" else {\n"+d+"}");return e+"\n"}; +Blockly.JavaScript.logic_compare=function(a){var b={EQ:"==",NEQ:"!=",LT:"<",LTE:"<=",GT:">",GTE:">="}[a.getFieldValue("OP")],c="=="==b||"!="==b?Blockly.JavaScript.ORDER_EQUALITY:Blockly.JavaScript.ORDER_RELATIONAL,d=Blockly.JavaScript.valueToCode(a,"A",c)||"0";a=Blockly.JavaScript.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; +Blockly.JavaScript.logic_operation=function(a){var b="AND"==a.getFieldValue("OP")?"&&":"||",c="&&"==b?Blockly.JavaScript.ORDER_LOGICAL_AND:Blockly.JavaScript.ORDER_LOGICAL_OR,d=Blockly.JavaScript.valueToCode(a,"A",c);a=Blockly.JavaScript.valueToCode(a,"B",c);if(d||a){var e="&&"==b?"true":"false";d||(d=e);a||(a=e)}else a=d="false";return[d+" "+b+" "+a,c]}; +Blockly.JavaScript.logic_negate=function(a){var b=Blockly.JavaScript.ORDER_LOGICAL_NOT;return["!"+(Blockly.JavaScript.valueToCode(a,"BOOL",b)||"true"),b]};Blockly.JavaScript.logic_boolean=function(a){return["TRUE"==a.getFieldValue("BOOL")?"true":"false",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.logic_null=function(a){return["null",Blockly.JavaScript.ORDER_ATOMIC]}; +Blockly.JavaScript.logic_ternary=function(a){var b=Blockly.JavaScript.valueToCode(a,"IF",Blockly.JavaScript.ORDER_CONDITIONAL)||"false",c=Blockly.JavaScript.valueToCode(a,"THEN",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";a=Blockly.JavaScript.valueToCode(a,"ELSE",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";return[b+" ? "+c+" : "+a,Blockly.JavaScript.ORDER_CONDITIONAL]}; \ No newline at end of file diff --git a/Blockly/brobot/jquery/images/ui-icons_444444_256x240.png b/Blockly/brobot/jquery/images/ui-icons_444444_256x240.png new file mode 100644 index 0000000..c2daae1 Binary files /dev/null and b/Blockly/brobot/jquery/images/ui-icons_444444_256x240.png differ diff --git a/Blockly/brobot/jquery/images/ui-icons_555555_256x240.png b/Blockly/brobot/jquery/images/ui-icons_555555_256x240.png new file mode 100644 index 0000000..4784928 Binary files /dev/null and b/Blockly/brobot/jquery/images/ui-icons_555555_256x240.png differ diff --git a/Blockly/brobot/jquery/images/ui-icons_777620_256x240.png b/Blockly/brobot/jquery/images/ui-icons_777620_256x240.png new file mode 100644 index 0000000..d2f58d2 Binary files /dev/null and b/Blockly/brobot/jquery/images/ui-icons_777620_256x240.png differ diff --git a/Blockly/brobot/jquery/images/ui-icons_777777_256x240.png b/Blockly/brobot/jquery/images/ui-icons_777777_256x240.png new file mode 100644 index 0000000..1d53258 Binary files /dev/null and b/Blockly/brobot/jquery/images/ui-icons_777777_256x240.png differ diff --git a/Blockly/brobot/jquery/images/ui-icons_cc0000_256x240.png b/Blockly/brobot/jquery/images/ui-icons_cc0000_256x240.png new file mode 100644 index 0000000..2825f20 Binary files /dev/null and b/Blockly/brobot/jquery/images/ui-icons_cc0000_256x240.png differ diff --git a/Blockly/brobot/jquery/images/ui-icons_ffffff_256x240.png b/Blockly/brobot/jquery/images/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000..136a4f9 Binary files /dev/null and b/Blockly/brobot/jquery/images/ui-icons_ffffff_256x240.png differ diff --git a/Blockly/brobot/jquery/jquery-3.1.1.min.js b/Blockly/brobot/jquery/jquery-3.1.1.min.js new file mode 100644 index 0000000..4c5be4c --- /dev/null +++ b/Blockly/brobot/jquery/jquery-3.1.1.min.js @@ -0,0 +1,4 @@ +/*! jQuery v3.1.1 | (c) jQuery Foundation | jquery.org/license */ +!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):C.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/[^\x20\t\r\n\f]+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R), +a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ka=/^$|\/(?:java|ecma)script/i,la={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};la.optgroup=la.option,la.tbody=la.tfoot=la.colgroup=la.caption=la.thead,la.th=la.td;function ma(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function na(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=ma(l.appendChild(f),"script"),j&&na(g),c){k=0;while(f=g[k++])ka.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var qa=d.documentElement,ra=/^key/,sa=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ta=/^([^.]*)(?:\.(.+)|)/;function ua(){return!0}function va(){return!1}function wa(){try{return d.activeElement}catch(a){}}function xa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)xa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=va;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(qa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,za=/\s*$/g;function Da(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Ea(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Fa(a){var b=Ba.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ga(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&Aa.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ia(f,b,c,d)});if(m&&(e=pa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(ma(e,"script"),Ea),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=ma(h),f=ma(a),d=0,e=f.length;d0&&na(g,!i&&ma(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ja(this,a,!0)},remove:function(a){return Ja(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.appendChild(a)}})},prepend:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(ma(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!za.test(a)&&!la[(ja.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function Ya(a,b,c,d,e){return new Ya.prototype.init(a,b,c,d,e)}r.Tween=Ya,Ya.prototype={constructor:Ya,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Ya.propHooks[this.prop];return a&&a.get?a.get(this):Ya.propHooks._default.get(this)},run:function(a){var b,c=Ya.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ya.propHooks._default.set(this),this}},Ya.prototype.init.prototype=Ya.prototype,Ya.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Ya.propHooks.scrollTop=Ya.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Ya.prototype.init,r.fx.step={};var Za,$a,_a=/^(?:toggle|show|hide)$/,ab=/queueHooks$/;function bb(){$a&&(a.requestAnimationFrame(bb),r.fx.tick())}function cb(){return a.setTimeout(function(){Za=void 0}),Za=r.now()}function db(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ba[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function eb(a,b,c){for(var d,e=(hb.tweeners[b]||[]).concat(hb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?ib:void 0)), +void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),ib={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=jb[b]||r.find.attr;jb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=jb[g],jb[g]=e,e=null!=c(a,b,d)?g:null,jb[g]=f),e}});var kb=/^(?:input|select|textarea|button)$/i,lb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):kb.test(a.nodeName)||lb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function mb(a){var b=a.match(K)||[];return b.join(" ")}function nb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,nb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,nb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,nb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=nb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(nb(c))+" ").indexOf(b)>-1)return!0;return!1}});var ob=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(ob,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:mb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ia.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,"$1"),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r("