diff --git a/gui b/gui index 90b266bf..3d9aa436 160000 --- a/gui +++ b/gui @@ -1 +1 @@ -Subproject commit 90b266bf71408ee5bef1da4cf1fcd4aefb13b33d +Subproject commit 3d9aa436b496eea99d6a8aa3c109e06db64fc6fd diff --git a/platformio.ini b/platformio.ini index ab7743bb..29e188c0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -36,7 +36,7 @@ lib_deps = ArduinoMongoose@0.0.14 Micro Debug@0.0.3 ConfigJson@0.0.3 - OpenEVSE@0.0.2 + OpenEVSE@0.0.3 ESPAL@0.0.1 StreamSpy@0.0.1 MicroTasks@0.0.1 @@ -219,31 +219,6 @@ framework = arduino, espidf # export PLATFORMIO_UPLOAD_PORT=172.16.0.157 # export PLATFORMIO_UPLOAD_FLAGS="-p 3232" -[env:openevse_huzzah32_dev] -platform = ${common.platform_esp32} -board = featheresp32 -framework = arduino -lib_deps = ${common.lib_deps} -src_build_flags = - ${common.version}.dev - ${common.src_build_flags} - ${common.src_build_flags_esp32} - -DWIFI_LED=13 - -DWIFI_LED_ON_STATE=HIGH - -DWIFI_BUTTON=0 - -DWIFI_BUTTON_PRESSED_STATE=LOW - -DRAPI_PORT=Serial - -DDEBUG_PORT=Serial2 - -DSERIAL_RX_PULLUP_PIN=3 - -DENABLE_DEBUG -build_flags = - ${common.build_flags} - ${common.build_flags_esp32} -upload_speed = 921600 -monitor_speed = 115200 -extra_scripts = ${common.extra_scripts} -board_build.partitions = ${common.build_partitions_esp32} - [env:openevse_huzzah32] platform = ${common.platform_esp32} board = featheresp32 @@ -257,9 +232,14 @@ src_build_flags = -DWIFI_LED_ON_STATE=HIGH -DWIFI_BUTTON=0 -DWIFI_BUTTON_PRESSED_STATE=LOW - -DRAPI_PORT=Serial - -DDEBUG_PORT=Serial2 - -DSERIAL_RX_PULLUP_PIN=3 + -DRAPI_PORT=Serial1 + -DRAPI_PORT_RX=GPIO_NUM_34 + -DRAPI_PORT_RX_PULLUP + -DRAPI_PORT_TX=GPIO_NUM_25 + -DRAPI_PORT_RESET=GPIO_NUM_26 + -DRAPI_PORT_RESET_ACTIVELOW + -DDEBUG_PORT=Serial + -DSMARTEVSE build_flags = ${common.build_flags} ${common.build_flags_esp32} @@ -268,6 +248,20 @@ monitor_speed = 115200 extra_scripts = ${common.extra_scripts} board_build.partitions = ${common.build_partitions_esp32} +[env:openevse_huzzah32_dev] +extends = env:openevse_huzzah32 +src_build_flags = ${env:openevse_huzzah32.src_build_flags} ${common.debug_flags_esp32} + +[env:openevse_huzzah32_ota] +extends = env:openevse_huzzah32 +upload_protocol = espota +upload_port = openevse.local + +[env:openevse_huzzah32_dev_ota] +extends = env:openevse_huzzah32_dev +upload_protocol = espota +upload_port = openevse.local + [env:openevse_huzzah32_idf] extends = env:openevse_huzzah32 framework = arduino, espidf diff --git a/src/app_config.cpp b/src/app_config.cpp index 36fe3acb..7ef33a81 100644 --- a/src/app_config.cpp +++ b/src/app_config.cpp @@ -56,6 +56,7 @@ uint32_t flags; String ohm; // Divert settings +String divert_feed_type; double divert_PV_ratio; double divert_attack_smoothing_factor; double divert_decay_smoothing_factor; @@ -110,6 +111,7 @@ ConfigOpt *opts[] = new ConfigOptDefenition(ohm, "", "ohm", "o"), // Divert settings + new ConfigOptDefenition(divert_feed_type, "grid_ie", "divert_feed_type", "dft"), new ConfigOptDefenition(divert_PV_ratio, 1.1, "divert_PV_ratio", "dpr"), new ConfigOptDefenition(divert_attack_smoothing_factor, 0.4, "divert_attack_smoothing_factor", "da"), new ConfigOptDefenition(divert_decay_smoothing_factor, 0.05, "divert_decay_smoothing_factor", "dd"), @@ -185,7 +187,7 @@ void config_changed(String name) mqtt_restart(); } else if(name.startsWith("emoncms_")) { emoncms_updated = true; - } else if(name == "divert_enabled" || name == "charge_mode") { + } else if(name == "divert_enabled" || name == "charge_mode" || name == "divert_feed_type") { DBUGVAR(config_divert_enabled()); DBUGVAR(config_charge_mode()); divertmode_update((config_divert_enabled() && 1 == config_charge_mode()) ? DIVERT_MODE_ECO : DIVERT_MODE_NORMAL); diff --git a/src/app_config.h b/src/app_config.h index 46c49c47..e0372de0 100644 --- a/src/app_config.h +++ b/src/app_config.h @@ -46,6 +46,7 @@ extern String mqtt_announce_topic; extern String time_zone; // Divert settings +extern String divert_feed_type; extern double divert_PV_ratio; extern double divert_attack_smoothing_factor; extern double divert_decay_smoothing_factor; diff --git a/src/debug.cpp b/src/debug.cpp index 7ae0b2b8..5a5ad930 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -3,11 +3,32 @@ StreamSpy SerialDebug(DEBUG_PORT); StreamSpy SerialEvse(RAPI_PORT); +#ifndef DEBUG_PORT_RX +#define DEBUG_PORT_RX -1 +#endif + +#ifndef DEBUG_PORT_TX +#define DEBUG_PORT_TX -1 +#endif + +#ifndef RAPI_PORT_RX +#define RAPI_PORT_RX -1 +#endif + +#ifndef RAPI_PORT_TX +#define RAPI_PORT_TX -1 +#endif + void debug_setup() { - DEBUG_PORT.begin(115200); + DEBUG_PORT.begin(115200, SERIAL_8N1, DEBUG_PORT_RX, DEBUG_PORT_TX); SerialDebug.begin(2048); - RAPI_PORT.begin(115200); + RAPI_PORT.begin(115200, SERIAL_8N1, RAPI_PORT_RX, RAPI_PORT_TX); SerialEvse.begin(2048); + +#if RAPI_PORT_RX != -1 && defined(RAPI_PORT_RX_PULLUP) + // https://forums.adafruit.com/viewtopic.php?f=57&t=153553&p=759890&hilit=esp32+serial+pullup#p769168 + pinMode(RAPI_PORT_RX, INPUT_PULLUP); +#endif } diff --git a/src/divert.cpp b/src/divert.cpp index 153e3b4f..7878bae4 100644 --- a/src/divert.cpp +++ b/src/divert.cpp @@ -67,45 +67,51 @@ time_t __attribute__((weak)) divertmode_get_time() // function called when divert mode is changed void divertmode_update(byte newmode) { - DBUGF("Set divertmode: %d", newmode); + DBUGF("Set divertmode: %d %s", newmode, divert_feed_type.c_str()); if(divertmode != newmode) { divertmode = newmode; - // restore max charge current if normal mode or zero if eco mode - switch(divertmode) - { - case DIVERT_MODE_NORMAL: - // Restore the max charge current - rapiSender.sendCmdSync(String(F("$SC ")) + String(max_charge_current)); - DBUGF("Restore max I: %d", max_charge_current); - break; - - case DIVERT_MODE_ECO: - charge_rate = 0; - available_current = 0; - smoothed_available_current = 0; - min_charge_end = 0; - - // Read the current charge current, assume this is the max set by the user - if(0 == rapiSender.sendCmdSync(F("$GE"))) { - max_charge_current = String(rapiSender.getToken(1)).toInt(); - DBUGF("Read max I: %d", max_charge_current); - } - if(OPENEVSE_STATE_SLEEPING != state) - { - if(0 == rapiSender.sendCmdSync(config_pause_uses_disabled() ? F("$FD") : F("$FS"))) + if (divert_feed_type == "internal") { + rapiSender.sendCmdSync(String(F("$SX ")) + String((divertmode==DIVERT_MODE_NORMAL)?1:2)); + } + else { + + // restore max charge current if normal mode or zero if eco mode + switch(divertmode) + { + case DIVERT_MODE_NORMAL: + // Restore the max charge current + rapiSender.sendCmdSync(String(F("$SC ")) + String(max_charge_current)); + DBUGF("Restore max I: %d", max_charge_current); + break; + + case DIVERT_MODE_ECO: + charge_rate = 0; + available_current = 0; + smoothed_available_current = 0; + min_charge_end = 0; + + // Read the current charge current, assume this is the max set by the user + if(0 == rapiSender.sendCmdSync(F("$GE"))) { + max_charge_current = String(rapiSender.getToken(1)).toInt(); + DBUGF("Read max I: %d", max_charge_current); + } + if(OPENEVSE_STATE_SLEEPING != state) { - DBUGLN(F("Divert activated, entered sleep mode")); - divert_active = false; + if(0 == rapiSender.sendCmdSync(config_pause_uses_disabled() ? F("$FD") : F("$FS"))) + { + DBUGLN(F("Divert activated, entered sleep mode")); + divert_active = false; + } } - } - break; + break; - default: - return; + default: + return; + } } - + StaticJsonDocument<128> event; event["divertmode"] = divertmode; event["divert_active"] = divert_active; @@ -135,7 +141,7 @@ void divert_update_state() } // If divert mode = Eco (2) - if (divertmode == DIVERT_MODE_ECO) + if (divertmode == DIVERT_MODE_ECO && divert_feed_type != "internal") { int current_charge_rate = charge_rate; diff --git a/src/input.cpp b/src/input.cpp index dd06c7f6..54b5d7c0 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -38,8 +38,14 @@ int espfree = 0; int rapi_command = 1; -double amp = 0; // OpenEVSE Current Sensor +double amp = 0; // OpenEVSE Current Sensor double voltage = DEFAULT_VOLTAGE; // Voltage from OpenEVSE or MQTT + +double amp_phase_sys[3] = {0,0,0}; // SmartEVSE system current per phase +double amp_phase[3] = {0,0,0}; // SmartEVSE EV current per phase +double volt_phase[3] = {0,0,0}; // SmartEVSE voltage per phase + + double temp1 = 0; // Sensor DS3232 Ambient bool temp1_valid = false; double temp2 = 0; // Sensor MCP9808 Ambiet @@ -50,6 +56,12 @@ long pilot = 0; // OpenEVSE Pilot Setting long state = OPENEVSE_STATE_STARTING; // OpenEVSE State long elapsed = 0; // Elapsed time (only valid if charging) +int smartevse_mode = SMARTEVSE_MODE_NORMAL; // SmartEVSE charge mode (NORMAL, SMART, SOLAR) + +#ifdef ENABLE_LEGACY_API +String estate = "Unknown"; // Common name for State +#endif + // Defaults OpenEVSE Settings byte rgb_lcd = 1; byte serial_dbg = 0; @@ -67,7 +79,7 @@ byte stuck_relay = 1; byte vent_ck = 1; byte temp_ck = 1; byte auto_start = 1; -String firmware = "-"; +String firmware = "0.0.0"; // TODO: change back to "-" String protocol = "-"; // Default OpenEVSE Fault Counters @@ -82,9 +94,24 @@ long watthour_total = 0; void create_rapi_json(JsonDocument &doc) { doc["amp"] = amp * AMPS_SCALE_FACTOR; + doc["amp/L1"] = amp_phase[0] * AMPS_SCALE_FACTOR; + doc["amp/L2"] = amp_phase[1] * AMPS_SCALE_FACTOR; + doc["amp/L3"] = amp_phase[2] * AMPS_SCALE_FACTOR; + doc["voltage"] = voltage * VOLTS_SCALE_FACTOR; + doc["voltage/L1"] = volt_phase[0] * VOLTS_SCALE_FACTOR; + doc["voltage/L2"] = volt_phase[1] * VOLTS_SCALE_FACTOR; + doc["voltage/L3"] = volt_phase[2] * VOLTS_SCALE_FACTOR; + + doc["main_amp/L1"] = amp_phase_sys[0] * AMPS_SCALE_FACTOR; + doc["main_amp/L2"] = amp_phase_sys[1] * AMPS_SCALE_FACTOR; + doc["main_amp/L3"] = amp_phase_sys[2] * AMPS_SCALE_FACTOR; + + doc["pilot"] = pilot; doc["wh"] = watthour_total; + doc["wh_current"] = wattsec / 3600; + doc["elapsed"] = elapsed; if(temp1_valid) { doc["temp1"] = temp1 * TEMP_SCALE_FACTOR; } else { @@ -112,6 +139,7 @@ void create_rapi_json(JsonDocument &doc) doc["state"] = state; doc["freeram"] = ESPAL.getFreeHeap(); doc["divertmode"] = divertmode; + doc["smartevse_mode"] = smartevse_mode; doc["srssi"] = WiFi.RSSI(); } @@ -213,6 +241,48 @@ update_rapi_values() { } } }); + case 7: + rapiSender.sendCmd("$GX", [](int ret) + { + if(RAPI_RESPONSE_OK == ret) { + if(rapiSender.getTokenCnt() >= 2) + { + smartevse_mode = strtol(rapiSender.getToken(1), NULL, 16); + if (smartevse_mode==2) { + if (config_charge_mode()!=1 || divert_feed_type!="internal" || divertmode!=DIVERT_MODE_ECO) { + config_set("charge_mode",String("eco")); + config_set("divert_feed_type", String("internal")); + divertmode_update(DIVERT_MODE_ECO); + } + } else { + if (config_charge_mode()==1 && (!config_divert_enabled() || divert_feed_type=="internal") ) + config_set("charge_mode",String("fast")); + } + } + } else { + if (config_charge_mode()==1 && (!config_divert_enabled() || divert_feed_type=="internal") ) + config_set("charge_mode",String("fast")); + } + }); + case 8: + rapiSender.sendCmd("$GY", [](int ret) + { + if(RAPI_RESPONSE_OK == ret) { + if(rapiSender.getTokenCnt() >= 10) + { + amp_phase_sys[0] = strtol(rapiSender.getToken(1), NULL, 10) / 1000.0; + amp_phase_sys[1] = strtol(rapiSender.getToken(2), NULL, 10) / 1000.0; + amp_phase_sys[2] = strtol(rapiSender.getToken(3), NULL, 10) / 1000.0; + amp_phase[0] = strtol(rapiSender.getToken(4), NULL, 10) / 1000.0; + amp_phase[1] = strtol(rapiSender.getToken(5), NULL, 10) / 1000.0; + amp_phase[2] = strtol(rapiSender.getToken(6), NULL, 10) / 1000.0; + volt_phase[0] = strtol(rapiSender.getToken(7), NULL, 10) / 1000.0; + volt_phase[1] = strtol(rapiSender.getToken(8), NULL, 10) / 1000.0; + volt_phase[2] = strtol(rapiSender.getToken(9), NULL, 10) / 1000.0; + } + } + }); + default: rapi_command = 0; //Last RAPI command break; } diff --git a/src/input.h b/src/input.h index 1e4e205b..02351d71 100644 --- a/src/input.h +++ b/src/input.h @@ -5,6 +5,10 @@ #include #include "RapiSender.h" +#define SMARTEVSE_MODE_NORMAL 0 +#define SMARTEVSE_MODE_SMART 1 +#define SMARTEVSE_MODE_SOLAR 2 + extern RapiSender rapiSender; extern String url; @@ -21,6 +25,8 @@ extern bool temp3_valid; extern long pilot; // OpenEVSE Pilot Setting extern long state; // OpenEVSE State extern long elapsed; // Elapsed time (only valid if charging) +extern String estate; // Common name for State +extern int smartevse_mode; // SmartEVSE charge mode (NORMAL, SMART, SOLAR) //Defaults OpenEVSE Settings extern byte rgb_lcd; diff --git a/src/main.cpp b/src/main.cpp index 2297605e..60dfc7e6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,7 @@ #include "time_man.h" #include "tesla_client.h" #include "event.h" +#include "update_controller.h" #include "LedManagerTask.h" @@ -120,109 +121,111 @@ loop() { Mongoose.poll(0); Profile_End(Mongoose, 10); - lcd_loop(); web_server_loop(); - net_loop(); -#ifdef ENABLE_OTA - ota_loop(); -#endif - rapiSender.loop(); - divert_current_loop(); - time_loop(); - MicroTask.update(); - - if(OpenEVSE.isConnected()) + if (!UpdateController.isRunning()) { - if(OPENEVSE_STATE_STARTING != state && - OPENEVSE_STATE_INVALID != state) + lcd_loop(); + net_loop(); + #ifdef ENABLE_OTA + ota_loop(); + #endif + rapiSender.loop(); + divert_current_loop(); + time_loop(); + + if(OpenEVSE.isConnected()) { - // Read initial state from OpenEVSE - if (rapi_read == 0) + if(OPENEVSE_STATE_STARTING != state && + OPENEVSE_STATE_INVALID != state) { - DBUGLN("first read RAPI values"); - handleRapiRead(); //Read all RAPI values - rapi_read=1; - } + // Read initial state from OpenEVSE + if (rapi_read == 0) + { + DBUGLN("first read RAPI values"); + handleRapiRead(); //Read all RAPI values + rapi_read=1; + } - // ------------------------------------------------------------------- - // Do these things once every 2s - // ------------------------------------------------------------------- - if ((millis() - Timer3) >= 2000) { - uint32_t current = ESPAL.getFreeHeap(); - int32_t diff = (int32_t)(last_mem - current); - if(diff != 0) { - DEBUG.printf("%s: Free memory %u - diff %d %d\n", time_format_time(time(NULL)).c_str(), current, diff, start_mem - current); - last_mem = current; + // ------------------------------------------------------------------- + // Do these things once every 500ms + // ------------------------------------------------------------------- + if ((millis() - Timer3) >= 500) { + /* + uint32_t current = ESPAL.getFreeHeap(); + int32_t diff = (int32_t)(last_mem - current); + if(diff != 0) { + DEBUG.printf("%s: Free memory %u - diff %d %d\n", time_format_time(time(NULL)).c_str(), current, diff, start_mem - current); + last_mem = current; + } + */ + update_rapi_values(); + Timer3 = millis(); } - update_rapi_values(); - Timer3 = millis(); } } - } - else - { - // Check if we can talk to OpenEVSE - if ((millis() - Timer3) >= 1000) + else { - // Check state the OpenEVSE is in. - OpenEVSE.begin(rapiSender, [](bool connected) + // Check if we can talk to OpenEVSE + if ((millis() - Timer3) >= 1000) { - if(connected) + // Check state the OpenEVSE is in. + OpenEVSE.begin(rapiSender, [](bool connected) { - OpenEVSE.getStatus([](int ret, uint8_t evse_state, uint32_t session_time, uint8_t pilot_state, uint32_t vflags) { - state = evse_state; - ledManager.setEvseState(evse_state); - }); - } else { - DBUGLN("OpenEVSE not responding or not connected"); - } - }); - Timer3 = millis(); + if(connected) + { + OpenEVSE.getStatus([](int ret, uint8_t evse_state, uint32_t session_time, uint8_t pilot_state, uint32_t vflags) { + state = evse_state; + }); + } else { + DBUGLN("OpenEVSE not responding or not connected"); + } + }); + Timer3 = millis(); + } } - } - if(net_is_connected()) - { - if (config_tesla_enabled()) { - teslaClient.loop(); - } + if(net_is_connected()) + { + if (config_tesla_enabled()) { + teslaClient.loop(); + } - mqtt_loop(); + mqtt_loop(); - // ------------------------------------------------------------------- - // Do these things once every 30 seconds - // ------------------------------------------------------------------- - if ((millis() - Timer1) >= 30000) { - DBUGLN("Time1"); + // ------------------------------------------------------------------- + // Do these things once every 10 seconds + // ------------------------------------------------------------------- + if ((millis() - Timer1) >= 10000) { + // DBUGLN("Time1"); - if(!Update.isRunning()) - { - DynamicJsonDocument data(4096); - create_rapi_json(data); // create JSON Strings for EmonCMS and MQTT + if(!Update.isRunning()) + { + DynamicJsonDocument data(4096); + create_rapi_json(data); // create JSON Strings for EmonCMS and MQTT - emoncms_publish(data); + emoncms_publish(data); - teslaClient.getChargeInfoJson(data); - event_send(data); + teslaClient.getChargeInfoJson(data); + event_send(data); - if(config_ohm_enabled()) { - ohm_loop(); + if(config_ohm_enabled()) { + ohm_loop(); + } } - } - - Timer1 = millis(); - } - if(emoncms_updated) - { - // Send the current state to check the config - DynamicJsonDocument data(4096); - create_rapi_json(data); - emoncms_publish(data); - emoncms_updated = false; - } - } // end WiFi connected + Timer1 = millis(); + } + if(emoncms_updated) + { + // Send the current state to check the config + DynamicJsonDocument data(4096); + create_rapi_json(data); + emoncms_publish(data); + emoncms_updated = false; + } + } // end WiFi connected + } // !UpdateController.isRunning() Profile_End(loop, 10); } // end loop @@ -248,9 +251,14 @@ void hardware_setup() { debug_setup(); -#ifdef SERIAL_RX_PULLUP_PIN - // https://forums.adafruit.com/viewtopic.php?f=57&t=153553&p=759890&hilit=esp32+serial+pullup#p769168 - pinMode(SERIAL_RX_PULLUP_PIN, INPUT_PULLUP); +#if defined(RAPI_PORT_RESET) && RAPI_PORT_RESET != -1 + #ifdef RAPI_PORT_RESET_ACTIVELOW + digitalWrite(RAPI_PORT_RESET, HIGH); + #else + digitalWrite(RAPI_PORT_RESET, LOW); + #endif + pinMatrixOutDetach(RAPI_PORT_RESET, false, false); + pinMode(RAPI_PORT_RESET, OUTPUT); #endif enableLoopWDT(); diff --git a/src/ota.cpp b/src/ota.cpp index 6b175db5..88644d9e 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -34,6 +34,7 @@ void ota_setup() lcd_display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW); lastPercent = percent; feedLoopWDT(); + yield(); } }); diff --git a/src/update_controller.cpp b/src/update_controller.cpp new file mode 100644 index 00000000..84aade1e --- /dev/null +++ b/src/update_controller.cpp @@ -0,0 +1,590 @@ + +#include +HardwareSerial &RAW_RAPI_PORT = RAPI_PORT; + +#include +#include "debug.h" +#include + +enum ControlCharacters +{ + STX = 0x0F, + ETX = 0x04, + DLE = 0x05 +}; + +enum BootloaderCommand +{ + GET_INFO = 0, + READ_FLASH = 1, + READ_FLASH_CRC = 2, + ERASE_FLASH = 3, + WRITE_FLASH = 4, + READ_EEPROM = 5, + WRITE_EEPROM = 6, + WRITE_CONFIG = 7, + RUN_APPLICATION = 8 +}; + +enum +{ + DATA = 0, + END_OF_FILE = 1, + EXTENDED_LINEAR_ADDRESS = 4 +}; + +static uint16_t crc_update(uint16_t crc, char data) +{ + unsigned int i; + bool bit; + unsigned char c = data; + + for (i = 0x80; i > 0; i >>= 1) + { + bit = crc & 0x8000; + if (c & i) + { + bit = !bit; + } + crc <<= 1; + if (bit) + { + crc ^= 0x1021; + } + } + + return crc; +} + +UpdateControllerClass::UpdateControllerClass() : _error(0), _size(0), _progress_callback(0), _progress(0) {} + +UpdateControllerClass &UpdateControllerClass::onProgress(THandlerFunction_Progress fn) +{ + // update progress on web page side + _progress_callback = fn; + return *this; +} + +void UpdateControllerClass::_resetController() +{ +#if defined(RAPI_PORT_RESET) && RAPI_PORT_RESET != -1 +#ifdef RAPI_PORT_RESET_ACTIVELOW + digitalWrite(RAPI_PORT_RESET, LOW); +#else + digitalWrite(RAPI_PORT_RESET, HIGH); +#endif + delay(10); +#ifdef RAPI_PORT_RESET_ACTIVELOW + digitalWrite(RAPI_PORT_RESET, HIGH); +#else + digitalWrite(RAPI_PORT_RESET, LOW); +#endif +#endif + + _receiveState = IDLE; + _buffer_pos = 0; +} + +static void _sendEscapedByte(char byte) +{ + if (byte == STX || byte == ETX || byte == DLE) + RAW_RAPI_PORT.write(DLE); + RAW_RAPI_PORT.write(byte); +} + +uint16_t UpdateControllerClass::_sendPacketStart(char *buf, size_t len) +{ + uint16_t crc = 0; + RAW_RAPI_PORT.write(STX); + + for (int i = 0; i < len; i++) + { + _sendEscapedByte(buf[i]); + crc = crc_update(crc, buf[i]); + } + + return crc; +} + +void UpdateControllerClass::_sendPacketEnd(uint16_t crc) +{ + _sendEscapedByte(crc & 0xff); + _sendEscapedByte(crc >> 8); + + RAW_RAPI_PORT.write(ETX); +} + +void UpdateControllerClass::_sendPacket(char *buf, size_t len) +{ + uint16_t crc = _sendPacketStart(buf, len); + _sendPacketEnd(crc); +} + +int UpdateControllerClass::_receiveByte(char byte, boolean nocrc) +{ + switch (_receiveState) + { + case ESCAPE: + if (_buffer_pos + 1 >= MAX_BUF_LEN) + { + DEBUG.printf("Buffer overrun in escape: %d %d", _buffer[0], _buffer[MAX_BUF_LEN - 1]); + return -1; + } + + _buffer[_buffer_pos++] = byte; + _receiveState = STARTED; + return 0; + case IDLE: + switch (byte) + { + case STX: + _receiveState = STARTED; + _buffer_pos = 0; + return 0; + case DLE: + _receiveState = ESCAPE; + return 0; + case ETX: + default: + return 0; + } + case STARTED: + switch (byte) + { + case STX: + _receiveState = STARTED; + _buffer_pos = 0; + return 0; + case ETX: + { + _receiveState = IDLE; + if (nocrc) + { + return _buffer_pos; + } + else + { + if (_buffer_pos < 2) + return -1; + else if (_buffer_pos == 2) + return 0; + + _buffer_pos -= 2; + + uint16_t crc_res = 0; + + for (int i = 0; i < _buffer_pos; i++) + crc_res = crc_update(crc_res, _buffer[i]); + + if ((_buffer[_buffer_pos] | (_buffer[_buffer_pos + 1] << 8)) != crc_res) + { + DEBUG_PORT.printf("CRC mismatch: %d != %d\n", crc_res, (_buffer[_buffer_pos] | (_buffer[_buffer_pos + 1] << 8))); + return -1; + } + return _buffer_pos; + } + } + case DLE: + _receiveState = ESCAPE; + return 0; + default: + if (_buffer_pos + 1 >= MAX_BUF_LEN) + { + DEBUG.printf("Buffer overrun: %d %d", _buffer[0], _buffer[MAX_BUF_LEN - 1]); + return -1; + } + _buffer[_buffer_pos++] = byte; + return 0; + } + default: + DEBUG_PORT.printf("Illegal state: %d\n", _receiveState); + _receiveState = IDLE; + return -1; + } +} + +int UpdateControllerClass::_receivePacket(boolean nocrc) +{ + unsigned long start = millis(); + + int res = 0; + do + { + int byte = RAW_RAPI_PORT.read(); + if (byte >= 0) + res = _receiveByte(byte, nocrc); + } while (res == 0 && millis() - start < PACKET_TIMEOUT); + + if (res == 0) + { // timed out + DEBUG_PORT.printf("Timeout receiving packet\n"); + return -1; + } + else + return res; +} + +#define SEND_PACKET(...) \ + { \ + char tmp[] = {__VA_ARGS__}; \ + _sendPacket(tmp, sizeof(tmp)); \ + } + +#define SEND_PACKET_DATA(data, len, cmd, ...) \ + { \ + char tmp[] = {cmd, __VA_ARGS__}; \ + uint16_t crc = _sendPacketStart(tmp, sizeof(tmp)); \ + for (int i = 0; i < len; i++) \ + { \ + _sendEscapedByte(data[i]); \ + crc = crc_update(crc, data[i]); \ + } \ + _sendPacketEnd(crc); \ + \ + RECEIVE_PACKET(false, 1, -1, "Failed writing packet"); \ + if (_buffer[0] != cmd) \ + { \ + DEBUG_PORT.println("Wrong acknowledgement "); \ + return -1; \ + } \ + } + +#define RECEIVE_PACKET(nocrc, expected, retval, error) \ + { \ + int len = _receivePacket(nocrc); \ + if (len != expected) \ + { \ + DEBUG_PORT.printf("%s (%d != %d)\n", error, len, expected); \ + return retval; \ + } \ + } + +bool UpdateControllerClass::begin(size_t size, int ledPin, uint8_t ledOn) +{ + _size = size; + + DEBUG_PORT.println("Entering bootloader"); + unsigned long start; + + // Try exiting bootloader if accidentally stuck + SEND_PACKET(RUN_APPLICATION); + RAW_RAPI_PORT.flush(); + + // Enter bootloader by causing framing error (switch to 300 baud and send 0s) + RAW_RAPI_PORT.updateBaudRate(300); + RAW_RAPI_PORT.write(0); + _resetController(); + RAW_RAPI_PORT.flush(); + RAW_RAPI_PORT.updateBaudRate(115200); + + // Detect bootloader started by sending STX till STX is returned + start = millis(); + char detectSTX = 0; + while ((detectSTX = RAW_RAPI_PORT.read()) != STX && millis() - start < PACKET_TIMEOUT) + { + if (detectSTX != 255) + DEBUG_PORT.printf("-: %d\n", detectSTX); + RAW_RAPI_PORT.write(STX); + yield(); + } + + if (detectSTX != STX) + { + DEBUG_PORT.printf("Timeout entering bootloader\n"); + return false; + } + + // Get information + SEND_PACKET(GET_INFO); + RECEIVE_PACKET(false, 10, false, "Error receiving bootloader info"); + + uint16_t bootloader_size = _buffer[0] | _buffer[1] << 8; + _bootloader_address = _buffer[6] | _buffer[7] << 8 | _buffer[8] << 16; + uint16_t bootloader_version_major = _buffer[2]; + uint16_t bootloader_version_minor = _buffer[3]; + uint16_t bootloader_device_type = _buffer[5] & 0xf; + + DEBUG_PORT.printf("Bootloader size: %4x, version: %d.%02d, %s, bootloader address: %04x\n", + bootloader_size, + bootloader_version_major, bootloader_version_minor, + bootloader_device_type == 4 ? "PIC18" : "PIC16", + _bootloader_address); + + if (bootloader_device_type != 4) + { + DEBUG_PORT.printf("Wrong device type (%d)\n", bootloader_device_type); + return false; + } + + if (bootloader_version_major != 1 && bootloader_version_minor != 6) + { + DEBUG_PORT.printf("Wrong bootloader version (%d.%02d != 1.06)\n", bootloader_version_major, bootloader_version_minor); + return false; + } + + SEND_PACKET(READ_FLASH, 0xfe, 0xff, 0x3f, 0x00, 0x2, 0x00); + + RECEIVE_PACKET(false, 2, false, "Error receiving device id"); + + uint16_t device_id = _buffer[1] << 3 | ((_buffer[0] & 0xe0) >> 5); + uint16_t device_revision = _buffer[1] & 0x1f; + DEBUG_PORT.printf("Device id: %04x, Revision: %d\n", device_id, device_revision); + + if (device_id != 0x02a2) + { + DEBUG_PORT.printf("Wrong device id (%d)\n", device_id); + return false; + } + + memset(_flashData, -1, FLASH_BLOCK_SIZE); + _flashStartAddress = 0; + _baseAddress = 0; + _data_char = 0; + _hexInRecord = false; + _flashBlocksWritten = 0; + + return true; +} + +int UpdateControllerClass::_flashBlock() +{ + if (_flashStartAddress >= 0x200000 && _flashStartAddress < 0x300000) + { + SEND_PACKET(READ_EEPROM, (char)((_flashStartAddress - 0x200000) & 0xff), (char)(((_flashStartAddress - 0x200000) >> 8) & 0xff), (char)(((_flashStartAddress - 0x200000) >> 16) & 0xff), 0x00, FLASH_BLOCK_SIZE, 0x00); + RECEIVE_PACKET(false, FLASH_BLOCK_SIZE, -1, "Failed reading eeprom"); + } + else + { + SEND_PACKET(READ_FLASH, (char)(_flashStartAddress & 0xff), (char)((_flashStartAddress >> 8) & 0xff), (char)((_flashStartAddress >> 16) & 0xff), 0x00, FLASH_BLOCK_SIZE, 0x00); + RECEIVE_PACKET(false, FLASH_BLOCK_SIZE, -1, "Failed reading flash"); + } + + // copy bootloader reset vector + if (_flashStartAddress == 0x0) + { + for (int i = 0; i < 4; i++) + { + _app_reset_vector[i] = _flashData[i]; + _flashData[i] = _buffer[i]; + } + } + + // copy original reset vector to just before bootloader + if (_flashStartAddress <= _bootloader_address - 4 && _flashStartAddress + FLASH_BLOCK_SIZE >= _bootloader_address) + { + for (int i = 0; i < 4; i++) + _flashData[_bootloader_address - 4 - _flashStartAddress + i] = _app_reset_vector[i]; + } + + bool matches = true; + for (int i = 0; i < FLASH_BLOCK_SIZE; i++) + if (_buffer[i] != _flashData[i]) + matches = false; + + if (!matches) + { + if (_flashStartAddress < 0x200000) + { + SEND_PACKET_DATA(_flashData, 0, ERASE_FLASH, (char)((_flashStartAddress + FLASH_BLOCK_SIZE - 1) & 0xff), (char)(((_flashStartAddress + FLASH_BLOCK_SIZE - 1) >> 8) & 0xff), (char)(((_flashStartAddress + FLASH_BLOCK_SIZE - 1) >> 16) & 0xff), 0x00, 1); + SEND_PACKET_DATA(_flashData, FLASH_BLOCK_SIZE, WRITE_FLASH, (char)((_flashStartAddress)&0xff), (char)(((_flashStartAddress) >> 8) & 0xff), (char)(((_flashStartAddress) >> 16) & 0xff), 0x00, 1); + } + else if ((_flashStartAddress >= 0x200000 && _flashStartAddress < 0x300000)) + { + // Skip EEPROM: keep existing values + // SEND_PACKET_DATA(_flashData, FLASH_BLOCK_SIZE, WRITE_EEPROM, (char)((_flashStartAddress - 0x200000) & 0xff), (char)(((_flashStartAddress - 0x200000) >> 8) & 0xff), (char)(((_flashStartAddress - 0x200000) >> 16) & 0xff), 0x00, FLASH_BLOCK_SIZE, 0x00); + } + else if ((_flashStartAddress >= 0x300000 && _flashStartAddress < 0x400000)) + { + // SkipCOnfig: keep existing values + // SEND_PACKET_DATA(_flashData, FLASH_BLOCK_SIZE, WRITE_CONFIG, (char)((_flashStartAddress - 0x300000) & 0xff), (char)(((_flashStartAddress - 0x300000) >> 8) & 0xff), (char)(((_flashStartAddress - 0x300000) >> 16) & 0xff), 0x00, FLASH_BLOCK_SIZE); + } + _flashBlocksWritten++; + } + + return 0; +} + +int UpdateControllerClass::_processRecord() +{ + // decode big-endian address + _hexData.address = (_hexData.raw[1] << 8) | _hexData.raw[2]; + + switch (_hexData.record_type) + { + case EXTENDED_LINEAR_ADDRESS: + _baseAddress = (((uint32_t)_hexData.data[0]) << 24) | (((uint32_t)_hexData.data[1]) << 16); + return 0; + case END_OF_FILE: + // flash last data + if (_flashBlock() < 0) + return -1; + return 0; + case DATA: + { + if (_hexData.byte_count == 0) + { + DEBUG_PORT.printf("Byte Count = 0\n"); + return -1; + } + uint32_t startAddress = _baseAddress | _hexData.address; + + uint32_t address = startAddress; + + while (address < startAddress + _hexData.byte_count) + { + if (address >= _flashStartAddress + FLASH_BLOCK_SIZE || address + _hexData.byte_count <= _flashStartAddress) + { // no interaction of HEX data and current flash block + if (_flashBlock() < 0) + { + return -1; + }; + + memset(_flashData, -1, FLASH_BLOCK_SIZE); + _flashStartAddress = address / FLASH_BLOCK_SIZE * FLASH_BLOCK_SIZE; + } + else if (address < _flashStartAddress && address + _hexData.byte_count > _flashStartAddress) + { // current HEX data starts before and overlaps start of flash block + DEBUG_PORT.println("HEX file with non-incremental addresses not supported"); + return -1; + } + else + { // current HEX data overlaps other part of flash block + size_t pos_in_buf = address - _flashStartAddress; + uint32_t data_size = min((unsigned int)_hexData.byte_count, FLASH_BLOCK_SIZE - pos_in_buf); + + memcpy(_flashData + pos_in_buf, _hexData.data + address - startAddress, data_size); + address += data_size; + } + } + + return 0; + } + default: + DEBUG_PORT.printf("Unsupported record type: type: %d, length: %d, addr: %04x\n", (int)_hexData.record_type, (int)_hexData.byte_count, (int)_hexData.address); + return -1; + } + return 0; +} + +int UpdateControllerClass::_readHex(uint8_t *data, size_t len) +{ + for (int pos = 0; pos < len; pos++) + { + if (!_hexInRecord) + { + if (data[pos] == ':') + { + _hexInRecord = true; + _data_char = 0; + } + else if (!isspace(data[pos])) + { + DEBUG_PORT.printf("Illegal character in input (%02x)\n", data[pos]); + return -1; + } + } + else + { + if (isxdigit(data[pos])) + { + if (_data_char % 2 == 0) + _hexData.raw[_data_char / 2] = ((data[pos] <= '9') ? data[pos] - '0' : (data[pos] & 0x7) + 9) << 4; + else + _hexData.raw[_data_char / 2] |= (data[pos] <= '9') ? data[pos] - '0' : (data[pos] & 0x7) + 9; + + _data_char++; + } + else if (isspace(data[pos])) + { + if (_data_char < 10) + { + DEBUG_PORT.printf("Record too short (%d<10)\n", _data_char); + return -1; + } + if (_hexData.byte_count * 2 + 10 != _data_char) + { + DEBUG_PORT.printf("Record length does not match with byte count (%d != %dx2+10)\n", _data_char, _hexData.byte_count); + return -1; + } + unsigned char crc = 0; + for (int i = 0; i < _data_char / 2; i++) + crc += _hexData.raw[i]; + if (crc != 0) + { + DEBUG_PORT.printf("Record CRC does not match (%02x!=0)\n", crc); + return -1; + } + + if (_processRecord() < 0) + { + return -1; + } + + _hexInRecord = false; + } + else + { + _hexInRecord = false; + DEBUG_PORT.printf("Illegal character in input (%02x)\n", data[pos]); + return -1; + } + } + } + return len; +} + +/* + Writes a buffer to the flash and increments the address + Returns the amount written +*/ +size_t UpdateControllerClass::write(uint8_t *data, size_t len) +{ + int res = _readHex(data, len); + if (res < 0) + res = 0; + + _progress += len; + yield(); + feedLoopWDT(); + + if (len != res) + { + DEBUG_PORT.println("Error: exiting bootloader"); + SEND_PACKET(RUN_APPLICATION); + _resetController(); + } + + return res; +} + +/* + End the running update +*/ +bool UpdateControllerClass::end(bool evenIfRemaining) +{ + DEBUG_PORT.printf("Success: Written %d bytes. Exiting bootloader\n", _flashBlocksWritten*FLASH_BLOCK_SIZE); + SEND_PACKET(RUN_APPLICATION); + _resetController(); + + _size = 0; + return true; +} + +/* + Aborts the running update +*/ +void UpdateControllerClass::abort() +{ + DEBUG_PORT.println("Aborting: Exiting bootloader"); + SEND_PACKET(RUN_APPLICATION); + _resetController(); + + _size = 0; +} + +/* + Prints the last error to an output stream +*/ +void UpdateControllerClass::printError(Stream &out) {} + +UpdateControllerClass UpdateController; diff --git a/src/update_controller.h b/src/update_controller.h new file mode 100644 index 00000000..c92a2e66 --- /dev/null +++ b/src/update_controller.h @@ -0,0 +1,157 @@ +#ifndef UPDATE_SMART_EVSE_H +#define UPDATE_SMART_EVSE_H + +#include +#include +#include +#include "esp_partition.h" + +#define UPDATE_ERROR_OK (0) +#define UPDATE_ERROR_WRITE (1) +#define UPDATE_ERROR_ERASE (2) +#define UPDATE_ERROR_READ (3) +#define UPDATE_ERROR_SPACE (4) +#define UPDATE_ERROR_SIZE (5) +#define UPDATE_ERROR_STREAM (6) +#define UPDATE_ERROR_MD5 (7) +#define UPDATE_ERROR_MAGIC_BYTE (8) +#define UPDATE_ERROR_ACTIVATE (9) +#define UPDATE_ERROR_NO_PARTITION (10) +#define UPDATE_ERROR_BAD_ARGUMENT (11) +#define UPDATE_ERROR_ABORT (12) + +#define UPDATE_SIZE_UNKNOWN 0xFFFFFFFF + +class UpdateControllerClass +{ +public: + typedef std::function THandlerFunction_Progress; + + UpdateControllerClass(); + + /* + This callback will be called when Update is receiving data + */ + UpdateControllerClass &onProgress(THandlerFunction_Progress fn); + + /* + Call this to check the space needed for the update + Will return false if there is not enough space + */ + bool begin(size_t size = UPDATE_SIZE_UNKNOWN, int ledPin = -1, uint8_t ledOn = LOW); + + /* + Writes a buffer to the flash and increments the address + Returns the amount written + */ + size_t write(uint8_t *data, size_t len); + + /* + If all bytes are written + this call will write the config to eboot + and return true + If there is already an update running but is not finished and !evenIfRemaining + or there is an error + this will clear everything and return false + the last error is available through getError() + evenIfRemaining is helpfull when you update without knowing the final size first + */ + bool end(bool evenIfRemaining = false); + + /* + Aborts the running update + */ + void abort(); + + /* + Prints the last error to an output stream + */ + void printError(Stream &out); + + const char *errorString(); + + //Helpers + uint8_t getError() { return _error; } + void clearError() { _error = UPDATE_ERROR_OK; } + bool hasError() { return _error != UPDATE_ERROR_OK; } + bool isRunning() { return _size > 0; } + bool isFinished() { return _progress == _size; } + size_t size() { return _size; } + size_t progress() { return _progress; } + size_t remaining() { return _size - _progress; } + +private: + void _reset(); + void _abort(uint8_t err); + bool _writeBuffer(); + bool _verifyHeader(uint8_t data); + bool _verifyEnd(); + + void _resetController(); + int _receivePacket(bool nocrc=false); + int _receiveByte(char byte, bool nocrc); + + uint16_t _sendPacketStart(char *buf, size_t len); + void _sendPacketEnd(uint16_t crc); + void _sendPacket(char *buf, size_t len); + + int _processRecord(); + int _readHex(uint8_t *data, size_t len); + + int _flashBlock(); + + uint8_t _error; + size_t _size; + + static const size_t MAX_BUF_LEN = 256; + uint8_t _buffer[MAX_BUF_LEN + 2]; + size_t _buffer_pos = 0; + + enum + { + IDLE, + STARTED, + ESCAPE + } _receiveState = IDLE; + + THandlerFunction_Progress _progress_callback; + uint32_t _progress; + + static const size_t MAX_HEX_RECORD_SIZE = 256 + 8 + 1; + static const size_t FLASH_BLOCK_SIZE = 64; + static const int PACKET_TIMEOUT = 1000; + + union + { + char raw[MAX_HEX_RECORD_SIZE]; + +#pragma pack(push, 1) + struct + { + uint8_t byte_count; + uint16_t address; + uint8_t record_type; + char data[]; + }; +#pragma pack(pop) + } _hexData; + + unsigned int _data_char; + + bool _hexInRecord = false; + uint32_t _baseAddress = 0; + + uint8_t _flashData[FLASH_BLOCK_SIZE]; + uint32_t _flashStartAddress; + + uint32_t _bootloader_address; + uint8_t _app_reset_vector[4]; + + uint32_t _flashBlocksWritten; + + +}; + +extern UpdateControllerClass UpdateController; + +#endif diff --git a/src/web_server.cpp b/src/web_server.cpp index f7898ff9..c390e475 100644 --- a/src/web_server.cpp +++ b/src/web_server.cpp @@ -4,6 +4,7 @@ #include #include +#include typedef const __FlashStringHelper *fstr_t; @@ -136,6 +137,8 @@ bool requestPreProcess(MongooseHttpServerRequest *request, MongooseHttpServerRes if(enableCors) { response->addHeader(F("Access-Control-Allow-Origin"), F("*")); + response->addHeader(F("Access-Control-Allow-Headers"), F("*")); + response->addHeader(F("Access-Control-Allow-Methods"), F("*")); } response->addHeader(F("Cache-Control"), F("no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0")); @@ -592,12 +595,15 @@ handleStatus(MongooseHttpServerRequest *request) { doc["nogndcount"] = nognd_count; doc["stuckcount"] = stuck_count; + doc["divertmode"] = divertmode; + doc["smartevse_mode"] = smartevse_mode; doc["solar"] = solar; doc["grid_ie"] = grid_ie; doc["charge_rate"] = charge_rate; doc["divert_update"] = (millis() - lastUpdate) / 1000; doc["ota_update"] = (int)Update.isRunning(); + doc["controller_update"] = (int)UpdateController.isRunning(); doc["time"] = String(time); doc["offset"] = String(offset); @@ -652,7 +658,7 @@ handleConfigGet(MongooseHttpServerRequest *request, MongooseHttpServerResponseSt JsonArray http_supported_protocols = doc.createNestedArray("http_supported_protocols"); http_supported_protocols.add("http"); http_supported_protocols.add("https"); - + config_serialize(doc, true, false, true); response->setCode(200); @@ -685,6 +691,8 @@ handleConfig(MongooseHttpServerRequest *request) handleConfigGet(request, response); } else if(HTTP_POST == request->method()) { handleConfigPost(request, response); + } else if(HTTP_OPTIONS == request->method()) { + response->setCode(200); } else { response->setCode(405); @@ -869,7 +877,145 @@ static void handleUpdateClose(MongooseHttpServerRequest *request) upgradeResponse = NULL; } - if(Update.isFinished() && !Update.hasError()) { + if (Update.isFinished() && !Update.hasError()) + { + systemRebootTime = millis() + 1000; + } +} + +// ------------------------------------------------------------------- +// Update Controller firmware +// url: /updateController +// ------------------------------------------------------------------- +void handleUpdateControllerGet(MongooseHttpServerRequest *request) +{ + MongooseHttpServerResponseStream *response; + if (false == requestPreProcess(request, response, CONTENT_TYPE_HTML)) + { + return; + } + + response->setCode(200); + response->print( + F("
" + " " + "" + "
")); + request->send(response); +} + +static MongooseHttpServerResponseStream *upgradeResponseController = NULL; + +void handleUpdateControllerPost(MongooseHttpServerRequest *request) +{ + if (NULL != upgradeResponseController) + { + request->send(500, CONTENT_TYPE_TEXT, "Error: Upgrade in progress"); + return; + } + + if (false == requestPreProcess(request, upgradeResponseController, CONTENT_TYPE_TEXT)) + { + return; + } + + // TODO: Add support for returning 100: Continue +} + +static int lastPercentController = -1; + +static void handleUpdateControllerError(MongooseHttpServerRequest *request) +{ + upgradeResponseController->setCode(500); + upgradeResponseController->printf("Error: %d", Update.getError()); + request->send(upgradeResponseController); + upgradeResponseController = NULL; + + // Anoyingly this uses Stream rather than Print... +#ifdef ENABLE_DEBUG + UpdateController.printError(DEBUG_PORT); +#endif +} + +size_t +handleUpdateControllerUpload(MongooseHttpServerRequest *request, int ev, MongooseString filename, uint64_t index, uint8_t *data, size_t len) +{ + if (MG_EV_HTTP_PART_BEGIN == ev) + { + // dumpRequest(request); + + DEBUG_PORT.printf("Update Start: %s\n", filename.c_str()); + + lcd_display(F("Updating Controller"), 0, 0, 0, LCD_CLEAR_LINE); + lcd_display(F(""), 0, 1, 10 * 1000, LCD_CLEAR_LINE); + lcd_loop(); + + if (!UpdateController.begin()) + { + handleUpdateControllerError(request); + } + } + + if (!UpdateController.hasError()) + { + DBUGF("Update Writing %llu", index); + + size_t contentLength = request->contentLength(); + DBUGVAR(contentLength); + if (contentLength > 0) + { + int percent = index / (contentLength / 100); + DBUGVAR(percent); + DBUGVAR(lastPercentController); + if (percent != lastPercentController) + { + String text = String(percent) + F("%"); + lcd_display(text, 0, 1, 10 * 1000, LCD_DISPLAY_NOW); + DEBUG_PORT.printf("Update: %d%%\n", percent); + lastPercentController = percent; + } + } + if (UpdateController.write(data, len) != len) + { + handleUpdateControllerError(request); + } + } + + if (MG_EV_HTTP_PART_END == ev) + { + DBUGLN("Upload finished"); + if (UpdateController.end(true)) + { + DBUGF("Update Success: %lluB", index + len); + lcd_display(F("Complete"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); + upgradeResponseController->setCode(200); + upgradeResponseController->print("OK"); + request->send(upgradeResponseController); + upgradeResponseController = NULL; + } + else + { + DBUGF("Update failed: %d", UpdateController.getError()); + lcd_display(F("Error"), 0, 1, 10 * 1000, LCD_CLEAR_LINE | LCD_DISPLAY_NOW); + handleUpdateControllerError(request); + } + } + + return len; +} + +static void handleUpdateControllerClose(MongooseHttpServerRequest *request) +{ + DBUGLN("Update close"); + + if (upgradeResponseController) + { + delete upgradeResponseController; + upgradeResponseController = NULL; + } + + if (UpdateController.isFinished() && !UpdateController.hasError()) + { systemRebootTime = millis() + 1000; } } @@ -1065,9 +1211,21 @@ web_server_setup() { onUpload(handleUpdateUpload)-> onClose(handleUpdateClose); + // Simple Firmware Update Form + server.on("/updateController$")->onRequest([](MongooseHttpServerRequest *request) { + if (HTTP_GET == request->method()) { + handleUpdateControllerGet(request); + } else if (HTTP_POST == request->method()) { + handleUpdateControllerPost(request); + } + })-> + onUpload(handleUpdateControllerUpload)-> + onClose(handleUpdateControllerClose); + server.on("/debug$", [](MongooseHttpServerRequest *request) { MongooseHttpServerResponseStream *response; - if(false == requestPreProcess(request, response, CONTENT_TYPE_TEXT)) { + if(false == requestPreProcess(request, response, CONTENT_TYPE_TEXT)) + { return; } diff --git a/src/web_static/web_server.home.html.h b/src/web_static/web_server.home.html.h index c0f35aeb..e3e9c1dc 100644 --- a/src/web_static/web_server.home.html.h +++ b/src/web_static/web_server.home.html.h @@ -1,19 +1,19 @@ static const char CONTENT_HOME_HTML[] PROGMEM = - " OpenEVSE

OpenEVSE

WiFi

Loading, please wait... (/)

WiFi Setup

Mode:

IP Address:

Successful packets:
of

OpenEVSE

RAPI packets:
of

Network RSSI dBm

IP Address:

Successful packets:
of

OpenEVSE

RAPI packets:
of

Connect to network:

Scanning...

SSID:

Passkey:

Connecting to WIFI Network...

Administration

Username:
15 characters max

Password:


15 characters max
Web interface HTTP authentication.

WiFi Firmware

Version:

Error:

Updating...
Firmware update completed ok

Advanced Settings

Hostname:
31 characters max

NTP Server:

Developer Mode

Enabled:

Serial Consoles

  Energy Monitoring

Emoncms Server*:
0 }\">

WiFi Setup

Mode:

IP Address:

Successful packets:
of

OpenEVSE

RAPI packets:
of

Network RSSI dBm

IP Address:

Successful packets:
of

OpenEVSE

RAPI packets:
of

Connect to network:

Scanning...

SSID:

Passkey:

Connecting to WIFI Network...

Administration

Username:
15 characters max

Password:


15 characters max
Web interface HTTP authentication.

Advanced Settings

Hostname:
31 characters max

NTP Server:

WiFi Firmware

Version:

Error:

Updating...
Firmware update completed ok

Controller Firmware

Version:

Error:

Updating...
Firmware update completed ok

Developer Mode

Enabled:

Serial Consoles

  Energy Monitoring

Emoncms Server*:
0 }\">

Emoncms Node*:

Emoncms write-apikey*:

Emoncms SSL SHA-1 Fingerprint (optional):


HTTPS will be enabled if present e.g: 7D:82:15:BE:D7:BC:72:58:87:7D:8E:40:D4:80:BA:1A:9F:8B:8D:DA

  Connected:    Successful posts: 

MQTT

Status published to:
{base-topic}/{status} value
e.g. /amp 16

RAPI control subscribes to:
{base-topic}/rapi/in/{command} value
e.g. /rapi/in/$SC 16
e.g. /rapi/in/$GC

RAPI response published to:
{base-topic}/rapi/out response
e.g. /rapi/out $OK 6 32

Emoncms Node*:

Emoncms write-apikey*:

Emoncms SSL SHA-1 Fingerprint (optional):


HTTPS will be enabled if present e.g: 7D:82:15:BE:D7:BC:72:58:87:7D:8E:40:D4:80:BA:1A:9F:8B:8D:DA

  Connected:    Successful posts: 

MQTT

Status published to:
{base-topic}/{status} value
e.g. /amp 16

RAPI control subscribes to:
{base-topic}/rapi/in/{command} value
e.g. /rapi/in/$SC 16
e.g. /rapi/in/$GC

RAPI response published to:
{base-topic}/rapi/out response
e.g. /rapi/out $OK 6 32

Host*:
0 }\">
e.g 'emonpi', 'test.mosquitto.org', '192.168.1.4'

Port*:

Reject self-signed certificates:

Warning!!

Certificate validation is disabled, although the connection to MQTT server will be encrypted the connection is still vulnerable to man-in-the-middle attacks.

Username: blank - no authentication

Password: blank - no authentication

Base-topic*:

e.g 'openevse'

Voltage topic:
Voltage MQTT topic to improve power calculations

  Connected: 

  OhmConnect

Click Here to Join

OhmConnect monitors real-time conditions on the electricity grid. When dirty and unsustainable power plants turn on, our users receive a notification to save energy.

Ohm Hour:

Ohm key:

USA - California only

Ohm Key can be obtained by logging in to OhmConnect, enter Settings and locate the link in \"Open Source Projects\"
Example: https://login.ohmconnect.com/verify-ohm-hour/OpnEoVse
Key: OpnEoVse

Solar PV divert

MQTT not enabled.

Solar PV Divert requires an SolarPV-gen or Grid (+I/-E) feed to be delivered via MQTT.
Dynamically adjust charge rate based on solar PV generation or excess power (grid export).

  • If only solar PV feed available: charge rate is modulated based on solar PV generation.
  • If grid +I/-E (positive Import / negative Export) feed is available: charge rate will be modulated by available excess power.
  • If EVSE is sleeping: charging will begin when solar PV / excess power > min charge rate.
  • Charging will pause if the excess power drops below the min charge rate for a period of time.
Note: It's assumed that EVSE power is included in the grid feed


Solar: Grid Import/Export: W - | Charge rate: A

Feed*:

Solar PV MQTT topic to modulate charge rate based on solar Grid (+I/-E) MQTT topic to modulate charge rate based on excess power

Required PV power ratio:

The fraction of PV current that suffices to start charging or increment current

Divert smoothing attack:

The amount of the new feed value to add to the divert available power rolling average

Divert smoothing decay:

The amount of the new feed value to remove to the divert available power rolling average

Minimum charge time:

The minimum amount of time (seconds) to charge the car once enabled via the Solar PV divert. This can help minimise wear and tear on the EVSE.

EVSE Error

EVSE Error

OpenEVSE not responding or not connected

e.g 'emonpi', 'test.mosquitto.org', '192.168.1.4'

Port*:

Reject self-signed certificates:

Warning!!

Certificate validation is disabled, although the connection to MQTT server will be encrypted the connection is still vulnerable to man-in-the-middle attacks.

Username: blank - no authentication

Password: blank - no authentication

Base-topic*:

e.g 'openevse'

Voltage topic:
Voltage MQTT topic to improve power calculations

  Connected: 

  OhmConnect

Click Here to Join

OhmConnect monitors real-time conditions on the electricity grid. When dirty and unsustainable power plants turn on, our users receive a notification to save energy.

Ohm Hour:

Ohm key:

USA - California only

Ohm Key can be obtained by logging in to OhmConnect, enter Settings and locate the link in \"Open Source Projects\"
Example: https://login.ohmconnect.com/verify-ohm-hour/OpnEoVse
Key: OpnEoVse

Solar PV divert

MQTT not enabled.

Solar PV Divert requires an SolarPV-gen or Grid (+I/-E) feed to be delivered via MQTT.
Dynamically adjust charge rate based on solar PV generation or excess power (grid export).

  • If only solar PV feed available: charge rate is modulated based on solar PV generation.
  • If grid +I/-E (positive Import / negative Export) feed is available: charge rate will be modulated by available excess power.
  • If EVSE is sleeping: charging will begin when solar PV / excess power > min charge rate.
  • Charging will pause if the excess power drops below the min charge rate for a period of time.
Note: It's assumed that EVSE power is included in the grid feed


Solar: Grid Import/Export: W - | Charge rate: A

Feed*:

Solar PV MQTT topic to modulate charge rate based on solar Grid (+I/-E) MQTT topic to modulate charge rate based on excess power SmartEVSE internal solar mode

Required PV power ratio:

The fraction of PV current that suffices to start charging or increment current

Divert smoothing attack:

The amount of the new feed value to add to the divert available power rolling average

Divert smoothing decay:

The amount of the new feed value to remove to the divert available power rolling average

Minimum charge time:

The minimum amount of time (seconds) to charge the car once enabled via the Solar PV divert. This can help minimise wear and tear on the EVSE.

EVSE Error

EVSE Error

OpenEVSE not responding or not connected

Session Status

Current Energy Temp Elapsed

Solar: Grid Import/Export: W - | Vehicle not connected Waiting for solar Charging from solar | Charge rate: A
Voltage: V | Available Current: A | Smoothed Current: A

Charge Options

Normal (fast) Eco (PV divert)


Time limit:

Eco (PV divert)


Time limit:



Timer:
Start:    Stop:

Energy

Energy
This Session:
Total:

Sensor Values

Sensor Value
Pilot:
Current Now:
Voltage:
Temp1:
Temp2:
Temp3:

Setup

Time: No RTC detected

Time:

Time zone:

Set time from

Service Level:

Max Current:

Set time from

Service Level:

Max Current:

Current

Name
Service Level:
Level Minimum:
Level Maximum:
Sensor Scale:
Sensor Offset:

Safety

Hardware safety checks. Enable dev mode (System > Developer Mode) to enable/disable or use the physical LCD + menu button.

Warning!!

Not all the safety tests are enabled, please take extra care before charging your vehicle.
Test Status
GFI Self Test:
Ground Monitoring:
Stuck Contact Detection:
Temperature Monitoring:
Diode Check:
Vent Required:
Error Count
GFCI:
No Ground:
Stuck Contact:

Hardware

OpenEVSE
Firmware:
Protocol:
OpenEVSE WiFi
Firmware:
Flash Size:
Free RAM:

Vehicle Settings

Pause status

Some vehicles will shutdown if left in sleep mode (pilot signal enable) and then can not be woken up by timers/PV divert. Changing the pause state to disable should resolve this issue, however this removes the ability for the charger to detect if a vehicle is connected when paused.
Sleep Disable

Current

Name
Service Level:
Level Minimum:
Level Maximum:
Sensor Scale:
Sensor Offset:

Safety

Hardware safety checks. Enable dev mode (System > Developer Mode) to enable/disable or use the physical LCD + menu button.

Warning!!

Not all the safety tests are enabled, please take extra care before charging your vehicle.
Test Status
GFI Self Test:
Ground Monitoring:
Stuck Contact Detection:
Temperature Monitoring:
Diode Check:
Vent Required:
Error Count
GFCI:
No Ground:
Stuck Contact:

Hardware

OpenEVSE
Firmware:
Protocol:
OpenEVSE WiFi
Firmware:
Flash Size:
Free RAM:

Vehicle Settings

Pause status

Some vehicles will shutdown if left in sleep mode (pilot signal enable) and then can not be woken up by timers/PV divert. Changing the pause state to disable should resolve this issue, however this removes the ability for the charger to detect if a vehicle is connected when paused.
Sleep Disable

Display

Simple Advanced

RAPI Command:

RAPI System Functions

Function Description
$FB LCD Backlight Color (0-7)
$FD Disable EVSE
$FE Enable EVSE
$FP Output text at x y position text to LCD (x y text)
$FR Reset EVSE
$FS Put EVSE to sleep
$FF Enable/disable feature (feature_id 0|1)
Front panel (B)utton, (D)iode check, G(F)I self-test, (G)round check, Stuck (R)elay check, (T)emp monitoring, (V)ent required

RAPI Get Commands

Get Description
$G0 Get EV connected state, not connected (0), connected (1), unknown (2)
$G3 Get Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$GA Get Ammeter Scale/Offset, scale offset
$GC Get current capacity range, integers
$GD Get delay timer, start_hour start_min end_hour end_min
$GE Get settings, amps flags
$GF Get fault counters, gfi ground stuck (in hex)
$GG Get charge current and voltage, milliamps millivolts
$GH Get charge limit in kWh, integer
$GM Get Voltmeter Scale/Offset, scale offset
$GP Get Temperatures, LCD MCP9808 infrared (integers, °C * 10)
$GS Get EVSE State, state elapsed_seconds
$GT Get time, year month day hour minute second
$GU Get Energy usage, wattseconds watt_hour_accumulated
$GV Get Versions, evse_firmware protocol_version

RAPI Set Commands

Set Description
$S0 Set LCD Type, Monochrome (0), Color (1)
$S1 Set RTC, year month day hour minute second (all 2-digit max)
$S2 Enable (1)/ Disable (0) Ammeter Calibration Mode
$S3 Set Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$SA Set Ammeter Scale/Offset, scale offset
$SC Set current capacity, integer
$SH Set charge limit in kWh, integer
$SK Set accumulated Wh, integer
$SL Set service level (1/2/A)
$SM Set Voltmeter Scale/Offset, scale offset
$ST Set timer, start_hour start_min end_hour end_min
$SV Set voltage for power calculations, millivolts

Powered by OpenEVSE and OpenEnergyMonitor
Version: V
\n"; + " left: advancedMode() || openevse.allTestsEnabled() }\">

Display

Simple Advanced

RAPI Command:

RAPI System Functions

Function Description
$FB LCD Backlight Color (0-7)
$FD Disable EVSE
$FE Enable EVSE
$FP Output text at x y position text to LCD (x y text)
$FR Reset EVSE
$FS Put EVSE to sleep
$FF Enable/disable feature (feature_id 0|1)
Front panel (B)utton, (D)iode check, G(F)I self-test, (G)round check, Stuck (R)elay check, (T)emp monitoring, (V)ent required

RAPI Get Commands

Get Description
$G0 Get EV connected state, not connected (0), connected (1), unknown (2)
$G3 Get Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$GA Get Ammeter Scale/Offset, scale offset
$GC Get current capacity range, integers
$GD Get delay timer, start_hour start_min end_hour end_min
$GE Get settings, amps flags
$GF Get fault counters, gfi ground stuck (in hex)
$GG Get charge current and voltage, milliamps millivolts
$GH Get charge limit in kWh, integer
$GM Get Voltmeter Scale/Offset, scale offset
$GP Get Temperatures, LCD MCP9808 infrared (integers, °C * 10)
$GS Get EVSE State, state elapsed_seconds
$GT Get time, year month day hour minute second
$GU Get Energy usage, wattseconds watt_hour_accumulated
$GV Get Versions, evse_firmware protocol_version
$GX Get current mode for SmartEVSE (0=Normal, 1=Smart, 2=Solar)
$GY Get per phase values (EV Amps L1,2,3; Main Amps L1,2,3; Voltage L1,2,3)

RAPI Set Commands

Set Description
$S0 Set LCD Type, Monochrome (0), Color (1)
$S1 Set RTC, year month day hour minute second (all 2-digit max)
$S2 Enable (1)/ Disable (0) Ammeter Calibration Mode
$S3 Set Charge Time Limit, 15-minutes (1), 30-minutes (2), etc...
$SA Set Ammeter Scale/Offset, scale offset
$SC Set current capacity, integer
$SH Set charge limit in kWh, integer
$SK Set accumulated Wh, integer
$SL Set service level (1/2/A)
$SM Set Voltmeter Scale/Offset, scale offset
$ST Set timer, start_hour start_min end_hour end_min
$SV Set voltage for power calculations, millivolts
$SX Set current mode for SmartEVSE (0=Normal, 1=Smart, 2=Solar)

Powered by OpenEVSE and OpenEnergyMonitor
Version: V
\n"; diff --git a/src/web_static/web_server.home.js.h b/src/web_static/web_server.home.js.h index 96595d30..37aac8f1 100644 --- a/src/web_static/web_server.home.js.h +++ b/src/web_static/web_server.home.js.h @@ -1,3 +1,3 @@ static const char CONTENT_HOME_JS[] PROGMEM = - "\"use strict\";function OpenEVSEError(e){var t=1\"+e.ret),t.cmd(e.cmd)},\"json\").always(function(){t.rapiSend(!1)})}}function TimeViewModel(n){var o=this;function r(e){return(e<10?\"0\":\"\")+e}o.evseTimedate=ko.observable(new Date),o.localTimedate=ko.observable(new Date),o.nowTimedate=ko.observable(null),o.hasRTC=ko.observable(!0),o.elapsedNow=ko.observable(new Date(0)),o.elapsedLocal=ko.observable(new Date),o.divertUpdateNow=ko.observable(new Date(0)),o.divertUpdateLocal=ko.observable(new Date),o.date=ko.pureComputed({read:function(){if(null===o.nowTimedate())return\"\";var e=o.nowTimedate();return e.getFullYear()+\"-\"+r(e.getMonth()+1)+\"-\"+r(e.getDate())},write:function(e){var t=o.evseTimedate();e+=\" \"+r(t.getHours())+\":\"+r(t.getMinutes())+\":\"+r(t.getSeconds()),o.evseTimedate(new Date(e)),o.localTimedate(new Date)}}),o.time=ko.pureComputed({read:function(){if(null===o.nowTimedate())return\"--:--:--\";var e=o.nowTimedate();return r(e.getHours())+\":\"+r(e.getMinutes())+\":\"+r(e.getSeconds())},write:function(e){var t=e.split(\":\"),e=o.evseTimedate();e.setHours(parseInt(t[0])),e.setMinutes(parseInt(t[1])),o.evseTimedate(e),o.localTimedate(new Date)}}),o.elapsed=ko.pureComputed(function(){if(null===o.nowTimedate())return\"0:00:00\";var e=o.elapsedNow().getTime(),t=(e=Math.floor(e/1e3))%60,n=(e=Math.floor(e/60))%60;return Math.floor(e/60)+\":\"+r(n)+\":\"+r(t)}),n.status.elapsed.subscribe(function(e){o.elapsedNow(new Date(1e3*e)),o.elapsedLocal(new Date)}),o.divert_update=ko.pureComputed(function(){if(null===o.nowTimedate())return!1;var e=o.divertUpdateNow().getTime();return Math.floor(e/1e3)}),n.status.divert_update.subscribe(function(e){o.divertUpdateNow(new Date(1e3*e)),o.divertUpdateLocal(new Date)});var a=null;o.automaticTime=ko.observable(!0),o.timeUpdate=function(e){var t=!(1=e){o.timeLimit(n.value);break}}},o.selectChargeLimit=function(e){if(o.chargeLimit()!==e)for(var t=0;t=e){o.chargeLimit(n.value);break}}};var a=[function(){return!1===o.status.time()?o.openevse.time(o.time.timeUpdate):new DummyRequest},function(){return o.openevse.service_level(function(e,t){o.serviceLevel(e),o.actualServiceLevel(t)})},function(){return o.updateCurrentCapacity()},function(){return o.openevse.current_capacity(function(e){o.currentCapacity(e)})},function(){return o.openevse.time_limit(function(e){o.selectTimeLimit(e)})},function(){return o.openevse.charge_limit(function(e){o.selectChargeLimit(e)})},function(){return o.openevse.gfi_self_test(function(e){o.gfiSelfTestEnabled(e)})},function(){return o.openevse.ground_check(function(e){o.groundCheckEnabled(e)})},function(){return o.openevse.stuck_relay_check(function(e){o.stuckRelayEnabled(e)})},function(){return o.openevse.temp_check(function(e){o.tempCheckEnabled(e)})},function(){return o.openevse.diode_check(function(e){o.diodeCheckEnabled(e)})},function(){return o.openevse.vent_required(function(e){o.ventRequiredEnabled(e)})},function(){return o.openevse.temp_check(function(){o.tempCheckSupported(!0)},o.tempCheckEnabled()).error(function(){o.tempCheckSupported(!1)})},function(){return o.openevse.timer(function(e,t,n){o.delayTimerEnabled(e),o.delayTimerStart(t),o.delayTimerStop(n)})}];o.updateCount=ko.observable(0),o.updateTotal=ko.observable(a.length),o.updateCurrentCapacity=function(){return o.openevse.current_capacity_range(function(e,t){o.minCurrentLevel(e),o.maxCurrentLevel(t);t=o.currentCapacity();o.currentLevels.removeAll();for(var n=o.minCurrentLevel();n<=o.maxCurrentLevel();n++)o.currentLevels.push({name:n+\" A\",value:n});o.currentCapacity(t)})},o.updatingServiceLevel=ko.observable(!1),o.savedServiceLevel=ko.observable(!1),o.updatingCurrentCapacity=ko.observable(!1),o.savedCurrentCapacity=ko.observable(!1),o.updatingTimeLimit=ko.observable(!1),o.savedTimeLimit=ko.observable(!1),o.updatingChargeLimit=ko.observable(!1),o.savedChargeLimit=ko.observable(!1),o.updatingDelayTimer=ko.observable(!1),o.savedDelayTimer=ko.observable(!1),o.updatingStatus=ko.observable(!1),o.savedStatus=ko.observable(!1),o.updatingGfiSelfTestEnabled=ko.observable(!1),o.savedGfiSelfTestEnabled=ko.observable(!1),o.updatingGroundCheckEnabled=ko.observable(!1),o.savedGroundCheckEnabled=ko.observable(!1),o.updatingStuckRelayEnabled=ko.observable(!1),o.savedStuckRelayEnabled=ko.observable(!1),o.updatingTempCheckEnabled=ko.observable(!1),o.savedTempCheckEnabled=ko.observable(!1),o.updatingDiodeCheckEnabled=ko.observable(!1),o.savedDiodeCheckEnabled=ko.observable(!1),o.updatingVentRequiredEnabled=ko.observable(!1),o.savedVentRequiredEnabled=ko.observable(!1);var i=!(o.setForTime=function(e,t){e(!0),setTimeout(function(){e(!1)},t)});function s(e){return/([01]\\d|2[0-3]):([0-5]\\d)/.test(e)}o.subscribe=function(){i||(o.serviceLevel.subscribe(function(e){o.updatingServiceLevel(!0),o.openevse.service_level(function(e,t){o.setForTime(o.savedServiceLevel,2e3),o.actualServiceLevel(t),o.updateCurrentCapacity().always(function(){})},e).always(function(){o.updatingServiceLevel(!1)})}),o.currentCapacity.subscribe(function(t){!0!==o.updatingServiceLevel()&&(o.updatingCurrentCapacity(!0),o.openevse.current_capacity(function(e){o.setForTime(o.savedCurrentCapacity,2e3),t!==e&&o.currentCapacity(e)},t).always(function(){o.updatingCurrentCapacity(!1)}))}),o.timeLimit.subscribe(function(t){o.updatingTimeLimit(!0),o.openevse.time_limit(function(e){o.setForTime(o.savedTimeLimit,2e3),t!==e&&o.selectTimeLimit(e)},t).always(function(){o.updatingTimeLimit(!1)})}),o.chargeLimit.subscribe(function(t){o.updatingChargeLimit(!0),o.openevse.charge_limit(function(e){o.setForTime(o.savedChargeLimit,2e3),t!==e&&o.selectChargeLimit(e)},t).always(function(){o.updatingChargeLimit(!1)})}),o.gfiSelfTestEnabled.subscribe(function(t){o.updatingGfiSelfTestEnabled(!0),o.openevse.gfi_self_test(function(e){o.setForTime(o.savedGfiSelfTestEnabled,2e3),t!==e&&o.gfiSelfTestEnabled(e)},t).always(function(){o.updatingGfiSelfTestEnabled(!1)})}),o.groundCheckEnabled.subscribe(function(t){o.updatingGroundCheckEnabled(!0),o.openevse.ground_check(function(e){o.setForTime(o.savedGroundCheckEnabled,2e3),t!==e&&o.groundCheckEnabled(e)},t).always(function(){o.updatingGroundCheckEnabled(!1)})}),o.stuckRelayEnabled.subscribe(function(t){o.updatingStuckRelayEnabled(!0),o.savedStuckRelayEnabled(!1),o.openevse.stuck_relay_check(function(e){o.savedStuckRelayEnabled(!0),setTimeout(function(){o.savedStuckRelayEnabled(!1)},2e3),t!==e&&o.stuckRelayEnabled(e)},t).always(function(){o.updatingStuckRelayEnabled(!1)})}),o.tempCheckEnabled.subscribe(function(t){o.updatingTempCheckEnabled(!0),o.openevse.temp_check(function(e){o.setForTime(o.savedTempCheckEnabled,2e3),t!==e&&o.tempCheckEnabled(e)},t).always(function(){o.updatingTempCheckEnabled(!1)})}),o.diodeCheckEnabled.subscribe(function(t){o.updatingDiodeCheckEnabled(!0),o.openevse.diode_check(function(e){o.setForTime(o.savedDiodeCheckEnabled,2e3),t!==e&&o.diodeCheckEnabled(e)},t).always(function(){o.updatingDiodeCheckEnabled(!1)})}),o.ventRequiredEnabled.subscribe(function(t){o.updatingVentRequiredEnabled(!0),o.openevse.vent_required(function(e){o.setForTime(o.savedVentRequiredEnabled,2e3),t!==e&&o.ventRequiredEnabled(e)},t).always(function(){o.updatingVentRequiredEnabled(!1)})}),i=!0)},o.update=function(){var e=0\"+e.ret),t.cmd(e.cmd)},\"json\").always(function(){t.rapiSend(!1)})}}function TimeViewModel(n){var o=this;function r(e){return(e<10?\"0\":\"\")+e}o.evseTimedate=ko.observable(new Date),o.localTimedate=ko.observable(new Date),o.nowTimedate=ko.observable(null),o.hasRTC=ko.observable(!0),o.elapsedNow=ko.observable(new Date(0)),o.elapsedLocal=ko.observable(new Date),o.divertUpdateNow=ko.observable(new Date(0)),o.divertUpdateLocal=ko.observable(new Date),o.date=ko.pureComputed({read:function(){if(null===o.nowTimedate())return\"\";var e=o.nowTimedate();return e.getFullYear()+\"-\"+r(e.getMonth()+1)+\"-\"+r(e.getDate())},write:function(e){var t=o.evseTimedate();e+=\" \"+r(t.getHours())+\":\"+r(t.getMinutes())+\":\"+r(t.getSeconds()),o.evseTimedate(new Date(e)),o.localTimedate(new Date)}}),o.time=ko.pureComputed({read:function(){if(null===o.nowTimedate())return\"--:--:--\";var e=o.nowTimedate();return r(e.getHours())+\":\"+r(e.getMinutes())+\":\"+r(e.getSeconds())},write:function(e){var t=e.split(\":\"),e=o.evseTimedate();e.setHours(parseInt(t[0])),e.setMinutes(parseInt(t[1])),o.evseTimedate(e),o.localTimedate(new Date)}}),o.elapsed=ko.pureComputed(function(){if(null===o.nowTimedate())return\"0:00:00\";var e=o.elapsedNow().getTime(),t=(e=Math.floor(e/1e3))%60,n=(e=Math.floor(e/60))%60;return Math.floor(e/60)+\":\"+r(n)+\":\"+r(t)}),n.status.elapsed.subscribe(function(e){o.elapsedNow(new Date(1e3*e)),o.elapsedLocal(new Date)}),o.divert_update=ko.pureComputed(function(){if(null===o.nowTimedate())return!1;var e=o.divertUpdateNow().getTime();return Math.floor(e/1e3)}),n.status.divert_update.subscribe(function(e){o.divertUpdateNow(new Date(1e3*e)),o.divertUpdateLocal(new Date)});var a=null;o.automaticTime=ko.observable(!0),o.timeUpdate=function(e){var t=!(1=e){o.timeLimit(n.value);break}}},o.selectChargeLimit=function(e){if(o.chargeLimit()!==e)for(var t=0;t=e){o.chargeLimit(n.value);break}}};var a=[function(){return!1===o.status.time()?o.openevse.time(o.time.timeUpdate):new DummyRequest},function(){return o.openevse.service_level(function(e,t){o.serviceLevel(e),o.actualServiceLevel(t)})},function(){return o.updateCurrentCapacity()},function(){return o.openevse.current_capacity(function(e){o.currentCapacity(e)})},function(){return o.openevse.time_limit(function(e){o.selectTimeLimit(e)})},function(){return o.openevse.charge_limit(function(e){o.selectChargeLimit(e)})},function(){return o.openevse.gfi_self_test(function(e){o.gfiSelfTestEnabled(e)})},function(){return o.openevse.ground_check(function(e){o.groundCheckEnabled(e)})},function(){return o.openevse.stuck_relay_check(function(e){o.stuckRelayEnabled(e)})},function(){return o.openevse.temp_check(function(e){o.tempCheckEnabled(e)})},function(){return o.openevse.diode_check(function(e){o.diodeCheckEnabled(e)})},function(){return o.openevse.vent_required(function(e){o.ventRequiredEnabled(e)})},function(){return o.openevse.temp_check(function(){o.tempCheckSupported(!0)},o.tempCheckEnabled()).error(function(){o.tempCheckSupported(!1)})},function(){return o.openevse.timer(function(e,t,n){o.delayTimerEnabled(e),o.delayTimerStart(t),o.delayTimerStop(n)})}];o.updateCount=ko.observable(0),o.updateTotal=ko.observable(a.length),o.updateCurrentCapacity=function(){return o.openevse.current_capacity_range(function(e,t){o.minCurrentLevel(e),o.maxCurrentLevel(t);t=o.currentCapacity();o.currentLevels.removeAll();for(var n=o.minCurrentLevel();n<=o.maxCurrentLevel();n++)o.currentLevels.push({name:n+\" A\",value:n});o.currentCapacity(t)})},o.updatingServiceLevel=ko.observable(!1),o.savedServiceLevel=ko.observable(!1),o.updatingCurrentCapacity=ko.observable(!1),o.savedCurrentCapacity=ko.observable(!1),o.updatingTimeLimit=ko.observable(!1),o.savedTimeLimit=ko.observable(!1),o.updatingChargeLimit=ko.observable(!1),o.savedChargeLimit=ko.observable(!1),o.updatingDelayTimer=ko.observable(!1),o.savedDelayTimer=ko.observable(!1),o.updatingStatus=ko.observable(!1),o.savedStatus=ko.observable(!1),o.updatingGfiSelfTestEnabled=ko.observable(!1),o.savedGfiSelfTestEnabled=ko.observable(!1),o.updatingGroundCheckEnabled=ko.observable(!1),o.savedGroundCheckEnabled=ko.observable(!1),o.updatingStuckRelayEnabled=ko.observable(!1),o.savedStuckRelayEnabled=ko.observable(!1),o.updatingTempCheckEnabled=ko.observable(!1),o.savedTempCheckEnabled=ko.observable(!1),o.updatingDiodeCheckEnabled=ko.observable(!1),o.savedDiodeCheckEnabled=ko.observable(!1),o.updatingVentRequiredEnabled=ko.observable(!1),o.savedVentRequiredEnabled=ko.observable(!1);var i=!(o.setForTime=function(e,t){e(!0),setTimeout(function(){e(!1)},t)});function s(e){return/([01]\\d|2[0-3]):([0-5]\\d)/.test(e)}o.subscribe=function(){i||(o.serviceLevel.subscribe(function(e){o.updatingServiceLevel(!0),o.openevse.service_level(function(e,t){o.setForTime(o.savedServiceLevel,2e3),o.actualServiceLevel(t),o.updateCurrentCapacity().always(function(){})},e).always(function(){o.updatingServiceLevel(!1)})}),o.currentCapacity.subscribe(function(t){!0!==o.updatingServiceLevel()&&(o.updatingCurrentCapacity(!0),o.openevse.current_capacity(function(e){o.setForTime(o.savedCurrentCapacity,2e3),t!==e&&o.currentCapacity(e)},t).always(function(){o.updatingCurrentCapacity(!1)}))}),o.timeLimit.subscribe(function(t){o.updatingTimeLimit(!0),o.openevse.time_limit(function(e){o.setForTime(o.savedTimeLimit,2e3),t!==e&&o.selectTimeLimit(e)},t).always(function(){o.updatingTimeLimit(!1)})}),o.chargeLimit.subscribe(function(t){o.updatingChargeLimit(!0),o.openevse.charge_limit(function(e){o.setForTime(o.savedChargeLimit,2e3),t!==e&&o.selectChargeLimit(e)},t).always(function(){o.updatingChargeLimit(!1)})}),o.gfiSelfTestEnabled.subscribe(function(t){o.updatingGfiSelfTestEnabled(!0),o.openevse.gfi_self_test(function(e){o.setForTime(o.savedGfiSelfTestEnabled,2e3),t!==e&&o.gfiSelfTestEnabled(e)},t).always(function(){o.updatingGfiSelfTestEnabled(!1)})}),o.groundCheckEnabled.subscribe(function(t){o.updatingGroundCheckEnabled(!0),o.openevse.ground_check(function(e){o.setForTime(o.savedGroundCheckEnabled,2e3),t!==e&&o.groundCheckEnabled(e)},t).always(function(){o.updatingGroundCheckEnabled(!1)})}),o.stuckRelayEnabled.subscribe(function(t){o.updatingStuckRelayEnabled(!0),o.savedStuckRelayEnabled(!1),o.openevse.stuck_relay_check(function(e){o.savedStuckRelayEnabled(!0),setTimeout(function(){o.savedStuckRelayEnabled(!1)},2e3),t!==e&&o.stuckRelayEnabled(e)},t).always(function(){o.updatingStuckRelayEnabled(!1)})}),o.tempCheckEnabled.subscribe(function(t){o.updatingTempCheckEnabled(!0),o.openevse.temp_check(function(e){o.setForTime(o.savedTempCheckEnabled,2e3),t!==e&&o.tempCheckEnabled(e)},t).always(function(){o.updatingTempCheckEnabled(!1)})}),o.diodeCheckEnabled.subscribe(function(t){o.updatingDiodeCheckEnabled(!0),o.openevse.diode_check(function(e){o.setForTime(o.savedDiodeCheckEnabled,2e3),t!==e&&o.diodeCheckEnabled(e)},t).always(function(){o.updatingDiodeCheckEnabled(!1)})}),o.ventRequiredEnabled.subscribe(function(t){o.updatingVentRequiredEnabled(!0),o.openevse.vent_required(function(e){o.setForTime(o.savedVentRequiredEnabled,2e3),t!==e&&o.ventRequiredEnabled(e)},t).always(function(){o.updatingVentRequiredEnabled(!1)})}),i=!0)},o.update=function(){var e=0>10|55296,1023&e|56320))}function r(){C()}var e,p,w,i,o,h,d,g,x,u,c,C,T,a,k,v,s,l,m,E=\"sizzle\"+ +new Date,b=n.document,S=0,y=0,_=ue(),N=ue(),A=ue(),D=ue(),O=function(e,t){return e===t&&(c=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,M=t.push,L=t.push,P=t.slice,R=function(e,t){for(var n=0,r=e.length;n+~]|\"+B+\")\"+B+\"*\"),z=new RegExp(B+\"|>\"),G=new RegExp($),X=new RegExp(\"^\"+H+\"$\"),Y={ID:new RegExp(\"^#(\"+H+\")\"),CLASS:new RegExp(\"^\\\\.(\"+H+\")\"),TAG:new RegExp(\"^(\"+H+\"|[*])\"),ATTR:new RegExp(\"^\"+F),PSEUDO:new RegExp(\"^\"+$),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+B+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+B+\"*(?:([+-]|)\"+B+\"*(\\\\d+)|))\"+B+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+I+\")$\",\"i\"),needsContext:new RegExp(\"^\"+B+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+B+\"*((?:-\\\\d)?\\\\d*)\"+B+\"*\\\\)|)(?=[^-]|$)\",\"i\")},K=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,Z=/^h\\d$/i,ee=/^[^{]+\\{\\s*\\[native \\w/,te=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ne=/[+~]/,re=new RegExp(\"\\\\\\\\[\\\\da-fA-F]{1,6}\"+B+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),oe=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"�\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},ae=be(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{L.apply(t=P.call(b.childNodes),b.childNodes),t[b.childNodes.length].nodeType}catch(e){L={apply:t.length?function(e,t){M.apply(e,P.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function se(t,e,n,r){var o,i,a,s,u,c,l,f=e&&e.ownerDocument,d=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==d&&9!==d&&11!==d)return n;if(!r&&(C(e),e=e||T,k)){if(11!==d&&(u=te.exec(t)))if(o=u[1]){if(9===d){if(!(a=e.getElementById(o)))return n;if(a.id===o)return n.push(a),n}else if(f&&(a=f.getElementById(o))&&m(e,a)&&a.id===o)return n.push(a),n}else{if(u[2])return L.apply(n,e.getElementsByTagName(t)),n;if((o=u[3])&&p.getElementsByClassName&&e.getElementsByClassName)return L.apply(n,e.getElementsByClassName(o)),n}if(p.qsa&&!D[t+\" \"]&&(!v||!v.test(t))&&(1!==d||\"object\"!==e.nodeName.toLowerCase())){if(l=t,f=e,1===d&&(z.test(t)||J.test(t))){for((f=ne.test(t)&&ge(e.parentNode)||e)===e&&p.scope||((s=e.getAttribute(\"id\"))?s=s.replace(oe,ie):e.setAttribute(\"id\",s=E)),i=(c=h(t)).length;i--;)c[i]=(s?\"#\"+s:\":scope\")+\" \"+me(c[i]);l=c.join(\",\")}try{return L.apply(n,f.querySelectorAll(l)),n}catch(e){D(t,!0)}finally{s===E&&e.removeAttribute(\"id\")}}}return g(t.replace(V,\"$1\"),e,n,r)}function ue(){var n=[];function r(e,t){return n.push(e+\" \")>w.cacheLength&&delete r[n.shift()],r[e+\" \"]=t}return r}function ce(e){return e[E]=!0,e}function le(e){var t=T.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)w.attrHandle[n[r]]=t}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function pe(t){return function(e){return\"form\"in e?e.parentNode&&!1===e.disabled?\"label\"in e?\"label\"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:\"label\"in e&&e.disabled===t}}function he(a){return ce(function(i){return i=+i,ce(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in p=se.support={},o=se.isXML=function(e){var t=e.namespaceURI,e=(e.ownerDocument||e).documentElement;return!K.test(t||e&&e.nodeName||\"HTML\")},C=se.setDocument=function(e){var t,e=e?e.ownerDocument||e:b;return e!=T&&9===e.nodeType&&e.documentElement&&(a=(T=e).documentElement,k=!o(T),b!=T&&(t=T.defaultView)&&t.top!==t&&(t.addEventListener?t.addEventListener(\"unload\",r,!1):t.attachEvent&&t.attachEvent(\"onunload\",r)),p.scope=le(function(e){return a.appendChild(e).appendChild(T.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),p.attributes=le(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),p.getElementsByTagName=le(function(e){return e.appendChild(T.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),p.getElementsByClassName=ee.test(T.getElementsByClassName),p.getById=le(function(e){return a.appendChild(e).id=E,!T.getElementsByName||!T.getElementsByName(E).length}),p.getById?(w.filter.ID=function(e){var t=e.replace(re,f);return function(e){return e.getAttribute(\"id\")===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&k){e=t.getElementById(e);return e?[e]:[]}}):(w.filter.ID=function(e){var t=e.replace(re,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return e&&e.value===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&k){var n,r,o,i=t.getElementById(e);if(i){if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i]}return[]}}),w.find.TAG=p.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):p.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if(\"*\"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},w.find.CLASS=p.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&k)return t.getElementsByClassName(e)},s=[],v=[],(p.qsa=ee.test(T.querySelectorAll))&&(le(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&v.push(\"[*^$]=\"+B+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||v.push(\"\\\\[\"+B+\"*(?:value|\"+I+\")\"),e.querySelectorAll(\"[id~=\"+E+\"-]\").length||v.push(\"~=\"),(t=T.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||v.push(\"\\\\[\"+B+\"*name\"+B+\"*=\"+B+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||v.push(\":checked\"),e.querySelectorAll(\"a#\"+E+\"+*\").length||v.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),v.push(\"[\\\\r\\\\n\\\\f]\")}),le(function(e){e.innerHTML=\"\";var t=T.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&v.push(\"name\"+B+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&v.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&v.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),v.push(\",.*:\")})),(p.matchesSelector=ee.test(l=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&le(function(e){p.disconnectedMatch=l.call(e,\"*\"),l.call(e,\"[s!='']:x\"),s.push(\"!=\",$)}),v=v.length&&new RegExp(v.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),m=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},O=t?function(e,t){if(e===t)return c=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!p.sortDetached&&t.compareDocumentPosition(e)===n?e==T||e.ownerDocument==b&&m(b,e)?-1:t==T||t.ownerDocument==b&&m(b,t)?1:u?R(u,e)-R(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return c=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==T?-1:t==T?1:o?-1:i?1:u?R(u,e)-R(u,t):0;if(o===i)return de(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?de(a[r],s[r]):a[r]==b?-1:s[r]==b?1:0}),T},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(C(e),p.matchesSelector&&k&&!D[t+\" \"]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=l.call(e,t);if(n||p.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){D(t,!0)}return 0\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(re,f),e[3]=(e[3]||e[4]||e[5]||\"\").replace(re,f),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Y.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&G.test(n)&&(t=h(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(re,f).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=_[e+\" \"];return t||(t=new RegExp(\"(^|\"+B+\")\"+e+\"(\"+B+\"|$)\"))&&_(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-1\",\"#\"===e.firstChild.getAttribute(\"href\")})||fe(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),p.attributes&&le(function(e){return e.innerHTML=\"\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||fe(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),le(function(e){return null==e.getAttribute(\"disabled\")})||fe(I,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(C);k.find=p,k.expr=p.selectors,k.expr[\":\"]=k.expr.pseudos,k.uniqueSort=k.unique=p.uniqueSort,k.text=p.getText,k.isXMLDoc=p.isXML,k.contains=p.contains,k.escapeSelector=p.escape;function x(e,t,n){for(var r=[],o=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(o&&k(e).is(n))break;r.push(e)}return r}function E(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var S=k.expr.match.needsContext;function _(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function A(e,n,r){return y(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(k.fn.init=function(e,t,n){if(!e)return this;if(n=n||D,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):y(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:O.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:T,!0)),N.test(r[1])&&k.isPlainObject(t))for(var r in t)y(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=T.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=k.fn,D=k(T);var j=/^(?:parents|prev(?:Until|All))/,q={children:!0,contents:!0,next:!0,prev:!0};function M(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,de=/^$|^module$|\\/(?:java|ecma)script/i;f=T.createDocumentFragment().appendChild(T.createElement(\"div\")),(p=T.createElement(\"input\")).setAttribute(\"type\",\"radio\"),p.setAttribute(\"checked\",\"checked\"),p.setAttribute(\"name\",\"t\"),f.appendChild(p),b.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",b.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",b.option=!!f.lastChild;var pe={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&_(e,t)?k.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var ve=/<|&#?\\w+;/;function me(e,t,n,r,o){for(var i,a,s,u,c,l=t.createDocumentFragment(),f=[],d=0,p=e.length;d\\s*$/g;function Ae(e,t){return _(e,\"table\")&&_(11!==t.nodeType?t:t.firstChild,\"tr\")&&k(e).children(\"tbody\")[0]||e}function De(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function Oe(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function je(e,t){var n,r,o,i;if(1===t.nodeType){if(X.hasData(e)&&(i=X.get(e).events))for(o in X.remove(t,\"handle events\"),i)for(n=0,r=i[o].length;n\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",o=function(e){r.remove(),o=null,e&&t(\"error\"===e.type?404:200,e.type)}),T.head.appendChild(r[0])},abort:function(){o&&o()}}});var Yt=[],Kt=/(=)\\?(?=&|$)|\\?\\?/;k.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Yt.pop()||k.expando+\"_\"+At.guid++;return this[e]=!0,e}}),k.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Kt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Kt.test(e.data)&&\"data\");if(a||\"jsonp\"===e.dataTypes[0])return r=e.jsonpCallback=y(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Kt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Dt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return i||k.error(r+\" was not called\"),i[0]},e.dataTypes[0]=\"json\",o=C[r],C[r]=function(){i=arguments},n.always(function(){void 0===o?k(C).removeProp(r):C[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Yt.push(r)),i&&y(o)&&o(i[0]),i=o=void 0}),\"script\"}),b.createHTMLDocument=((f=T.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===f.childNodes.length),k.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(b.createHTMLDocument?((r=(t=T.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=T.location.href,t.head.appendChild(r)):t=T),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=me([e],t,r),r&&r.length&&k(r).remove(),k.merge([],n.childNodes)));var r},k.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(\" \");return-1\").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,o,i,a,s=k.css(e,\"position\"),u=k(e),c={};\"static\"===s&&(e.style.position=\"relative\"),i=u.offset(),r=k.css(e,\"top\"),a=k.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(o=(s=u.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),y(t)&&(t=t.call(e,n,k.extend({},i))),null!=t.top&&(c.top=t.top-i.top+o),null!=t.left&&(c.left=t.left-i.left+a),\"using\"in t?t.using.call(e,c):(\"number\"==typeof c.top&&(c.top+=\"px\"),\"number\"==typeof c.left&&(c.left+=\"px\"),u.css(c))}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],o={top:0,left:0};if(\"fixed\"===k.css(r,\"position\"))t=r.getBoundingClientRect();else{for(t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;e&&(e===n.body||e===n.documentElement)&&\"static\"===k.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=k(e).offset()).top+=k.css(e,\"borderTopWidth\",!0),o.left+=k.css(e,\"borderLeftWidth\",!0))}return{top:t.top-o.top-k.css(r,\"marginTop\",!0),left:t.left-o.left-k.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===k.css(e,\"position\");)e=e.offsetParent;return e||re})}}),k.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,o){var i=\"pageYOffset\"===o;k.fn[t]=function(e){return $(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[o]:e[t]:void(r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),k.each([\"top\",\"left\"],function(e,n){k.cssHooks[n]=Ye(b.pixelPosition,function(e,t){if(t)return t=Xe(e,n),Ve.test(t)?k(e).position()[n]+\"px\":t})}),k.each({Height:\"height\",Width:\"width\"},function(a,s){k.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,i){k.fn[i]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),o=r||(!0===e||!0===t?\"margin\":\"border\");return $(this,function(e,t,n){var r;return g(e)?0===i.indexOf(\"outer\")?e[\"inner\"+a]:e.document.documentElement[\"client\"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body[\"scroll\"+a],r[\"scroll\"+a],e.body[\"offset\"+a],r[\"offset\"+a],r[\"client\"+a])):void 0===n?k.css(e,t,o):k.style(e,t,n,o)},s,n?e:void 0,n)}})}),k.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.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(e,n){k.fn[n]=function(e,t){return 0e.length)&&e.substring(0,t.length)===t},vd:function(e,t){if(e===t)return!0;if(11===e.nodeType)return!1;if(t.contains)return t.contains(1!==e.nodeType?e.parentNode:e);if(t.compareDocumentPosition)return 16==(16&t.compareDocumentPosition(e));for(;e&&e!=t;)e=e.parentNode;return!!e},Sb:function(e){return N.a.vd(e,e.ownerDocument.documentElement)},kd:function(e){return!!N.a.Lb(e,N.a.Sb)},R:function(e){return e&&e.tagName&&e.tagName.toLowerCase()},Ac:function(e){return N.onError?function(){try{return e.apply(this,arguments)}catch(e){throw N.onError&&N.onError(e),e}}:e},setTimeout:(c=function(e,t){return setTimeout(N.a.Ac(e),t)},h.toString=function(){return c.toString()},h),Gc:function(e){setTimeout(function(){throw N.onError&&N.onError(e),e},0)},B:function(t,e,n){var r=N.a.Ac(n);if(n=l[e],N.options.useOnlyNativeEvents||n||!Ne)if(n||\"function\"!=typeof t.addEventListener){if(void 0===t.attachEvent)throw Error(\"Browser doesn't support addEventListener or attachEvent\");var o=function(e){r.call(t,e)},i=\"on\"+e;t.attachEvent(i,o),N.a.K.za(t,function(){t.detachEvent(i,o)})}else t.addEventListener(e,r,!1);else u=u||(\"function\"==typeof Ne(t).on?\"on\":\"bind\"),Ne(t)[u](e,r)},Fb:function(e,t){if(!e||!e.nodeType)throw Error(\"element must be a DOM node when calling triggerEvent\");var n=!(\"input\"!==N.a.R(e)||!e.type||\"click\"!=t.toLowerCase())&&(\"checkbox\"==(n=e.type)||\"radio\"==n);if(N.options.useOnlyNativeEvents||!Ne||n)if(\"function\"==typeof Se.createEvent){if(\"function\"!=typeof e.dispatchEvent)throw Error(\"The supplied element doesn't support dispatchEvent\");(n=Se.createEvent(s[t]||\"HTMLEvents\")).initEvent(t,!0,!0,Ee,0,0,0,0,0,!1,!1,!1,!1,0,e),e.dispatchEvent(n)}else if(n&&e.click)e.click();else{if(void 0===e.fireEvent)throw Error(\"Browser doesn't support triggering events\");e.fireEvent(\"on\"+t)}else Ne(e).trigger(t)},f:function(e){return N.O(e)?e():e},bc:function(e){return N.O(e)?e.v():e},Eb:function(t,e,n){var r;e&&(\"object\"===_typeof(t.classList)?(r=t.classList[n?\"add\":\"remove\"],N.a.D(e.match(p),function(e){r.call(t.classList,e)})):\"string\"==typeof t.className.baseVal?o(t.className,\"baseVal\",e,n):o(t,\"className\",e,n))},Bb:function(e,t){var n=N.a.f(t);null!==n&&n!==ke||(n=\"\");t=N.h.firstChild(e);!t||3!=t.nodeType||N.h.nextSibling(t)?N.h.va(e,[e.ownerDocument.createTextNode(n)]):t.data=n,N.a.Ad(e)},Yc:function(e,t){if(e.name=t,d<=7)try{var n=e.name.replace(/[&<>'\"]/g,function(e){return\"&#\"+e.charCodeAt(0)+\";\"});e.mergeAttributes(Se.createElement(\"\"),!1)}catch(e){}},Ad:function(e){9<=d&&((e=1==e.nodeType?e:e.parentNode).style&&(e.style.zoom=e.style.zoom))},wd:function(e){var t;d&&(t=e.style.width,e.style.width=0,e.style.width=t)},Pd:function(e,t){e=N.a.f(e),t=N.a.f(t);for(var n=[],r=e;r<=t;r++)n.push(r);return n},la:function(e){for(var t=[],n=0,r=e.length;n\",\"\"],tbody:e,tfoot:e,tr:[2,\"\",\"
\"],td:e=[3,\"\",\"
\"],th:e,option:e=[1,\"\"],optgroup:e},f=N.a.W<=8,N.a.ua=function(e,t){var n;if(Ne){if(Ne.parseHTML)n=Ne.parseHTML(e,t)||[];else if((n=Ne.clean([e],t))&&n[0]){for(var r=n[0];r.parentNode&&11!==r.parentNode.nodeType;)r=r.parentNode;r.parentNode&&r.parentNode.removeChild(r)}}else{(n=t)||(n=Se);var r=n.parentWindow||n.defaultView||Ee,o=N.a.Db(e).toLowerCase(),i=n.createElement(\"div\"),t=(o=o.match(/^(?:\\x3c!--.*?--\\x3e\\s*?)*?<([a-z]+)[\\s>]/))&&l[o[1]]||u,o=t[0];for(t=\"ignored
\"+t[1]+e+t[2]+\"
\",\"function\"==typeof r.innerShiv?i.appendChild(r.innerShiv(t)):(f&&n.body.appendChild(i),i.innerHTML=t,f&&i.parentNode.removeChild(i));o--;)i=i.lastChild;n=N.a.la(i.lastChild.childNodes)}return n},N.a.Md=function(e,t){t=N.a.ua(e,t);return t.length&&t[0].parentElement||N.a.Yb(t)},N.a.fc=function(e,t){if(N.a.Tb(e),null!==(t=N.a.f(t))&&t!==ke)if(\"string\"!=typeof t&&(t=t.toString()),Ne)Ne(e).html(t);else for(var n=N.a.ua(t,e.ownerDocument),r=0;r]*))?)*\\s+)data-bind\\s*=\\s*([\"'])([\\s\\S]*?)\\3/gi,be=/\\x3c!--\\s*ko\\b\\s*([\\s\\S]*?)\\s*--\\x3e/g,{xd:function(e,t,n){t.isTemplateRewritten(e,n)||t.rewriteTemplate(e,function(e){return N.kc.Ld(e,t)},n)},Ld:function(e,i){return e.replace(me,function(e,t,n,r,o){return Ce(o,t,n,i)}).replace(be,function(e,t){return Ce(t,\"\\x3c!-- ko --\\x3e\",\"#comment\",i)})},md:function(n,r){return N.aa.Xb(function(e,t){e=e.nextSibling;e&&e.nodeName.toLowerCase()===r&&N.ib(e,n,t)})}}),N.b(\"__tr_ambtns\",N.kc.md),function(){N.C={},N.C.F=function(e){var t;(this.F=e)&&(t=N.a.R(e),this.ab=\"script\"===t?1:\"textarea\"===t?2:\"template\"==t&&e.content&&11===e.content.nodeType?3:4)},N.C.F.prototype.text=function(){var e=1===this.ab?\"text\":2===this.ab?\"value\":\"innerHTML\";if(0==arguments.length)return this.F[e];var t=arguments[0];\"innerHTML\"==e?N.a.fc(this.F,t):this.F[e]=t};var t=N.a.g.Z()+\"_\";N.C.F.prototype.data=function(e){if(1===arguments.length)return N.a.g.get(this.F,t+e);N.a.g.set(this.F,t+e,arguments[1])};var o=N.a.g.Z();N.C.F.prototype.nodes=function(){var e=this.F;if(0==arguments.length){var t,n=N.a.g.get(e,o)||{},r=n.lb||(3===this.ab?e.content:4===this.ab?e:ke);return r&&!n.jd||(t=this.text())&&t!==n.bb&&(r=N.a.Md(t,e.ownerDocument),N.a.g.set(e,o,{lb:r,bb:t,jd:!0})),r}n=arguments[0],this.ab!==ke&&this.text(\"\"),N.a.g.set(e,o,{lb:n})},N.C.ia=function(e){this.F=e},N.C.ia.prototype=new N.C.F,N.C.ia.prototype.constructor=N.C.ia,N.C.ia.prototype.text=function(){if(0==arguments.length){var e=N.a.g.get(this.F,o)||{};return e.bb===ke&&e.lb&&(e.bb=e.lb.innerHTML),e.bb}N.a.g.set(this.F,o,{bb:arguments[0]})},N.b(\"templateSources\",N.C),N.b(\"templateSources.domElement\",N.C.F),N.b(\"templateSources.anonymousTemplate\",N.C.ia)}(),function(){function r(e,t,n){var r;for(t=N.h.nextSibling(t);e&&(r=e)!==t;)n(r,e=N.h.nextSibling(r))}function d(e,t){if(e.length){var o=e[0],i=e[e.length-1],n=o.parentNode,a=N.ga.instance,s=a.preprocessNode;if(s){if(r(o,i,function(e,t){var n=e.previousSibling,r=s.call(a,e);r&&(e===o&&(o=r[0]||t),e===i&&(i=r[r.length-1]||n))}),e.length=0,!o)return;o===i?e.push(o):(e.push(o,i),N.a.Ua(e,n))}r(o,i,function(e){1!==e.nodeType&&8!==e.nodeType||N.vc(t,e)}),r(o,i,function(e){1!==e.nodeType&&8!==e.nodeType||N.aa.cd(e,[t])}),N.a.Ua(e,n)}}function u(e){return e.nodeType?e:0\"+t+\"<\\/script>\")},0>10|55296,1023&e|56320))}function r(){C()}var e,p,w,i,o,h,d,g,x,u,c,C,T,a,k,v,s,l,m,E=\"sizzle\"+ +new Date,b=n.document,S=0,y=0,_=ue(),N=ue(),A=ue(),D=ue(),O=function(e,t){return e===t&&(c=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,M=t.push,L=t.push,P=t.slice,R=function(e,t){for(var n=0,r=e.length;n+~]|\"+B+\")\"+B+\"*\"),z=new RegExp(B+\"|>\"),G=new RegExp($),X=new RegExp(\"^\"+H+\"$\"),Y={ID:new RegExp(\"^#(\"+H+\")\"),CLASS:new RegExp(\"^\\\\.(\"+H+\")\"),TAG:new RegExp(\"^(\"+H+\"|[*])\"),ATTR:new RegExp(\"^\"+F),PSEUDO:new RegExp(\"^\"+$),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+B+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+B+\"*(?:([+-]|)\"+B+\"*(\\\\d+)|))\"+B+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+I+\")$\",\"i\"),needsContext:new RegExp(\"^\"+B+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+B+\"*((?:-\\\\d)?\\\\d*)\"+B+\"*\\\\)|)(?=[^-]|$)\",\"i\")},K=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,Z=/^h\\d$/i,ee=/^[^{]+\\{\\s*\\[native \\w/,te=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ne=/[+~]/,re=new RegExp(\"\\\\\\\\[\\\\da-fA-F]{1,6}\"+B+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),oe=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"�\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},ae=be(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{L.apply(t=P.call(b.childNodes),b.childNodes),t[b.childNodes.length].nodeType}catch(e){L={apply:t.length?function(e,t){M.apply(e,P.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function se(t,e,n,r){var o,i,a,s,u,c,l,f=e&&e.ownerDocument,d=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==d&&9!==d&&11!==d)return n;if(!r&&(C(e),e=e||T,k)){if(11!==d&&(u=te.exec(t)))if(o=u[1]){if(9===d){if(!(a=e.getElementById(o)))return n;if(a.id===o)return n.push(a),n}else if(f&&(a=f.getElementById(o))&&m(e,a)&&a.id===o)return n.push(a),n}else{if(u[2])return L.apply(n,e.getElementsByTagName(t)),n;if((o=u[3])&&p.getElementsByClassName&&e.getElementsByClassName)return L.apply(n,e.getElementsByClassName(o)),n}if(p.qsa&&!D[t+\" \"]&&(!v||!v.test(t))&&(1!==d||\"object\"!==e.nodeName.toLowerCase())){if(l=t,f=e,1===d&&(z.test(t)||J.test(t))){for((f=ne.test(t)&&ge(e.parentNode)||e)===e&&p.scope||((s=e.getAttribute(\"id\"))?s=s.replace(oe,ie):e.setAttribute(\"id\",s=E)),i=(c=h(t)).length;i--;)c[i]=(s?\"#\"+s:\":scope\")+\" \"+me(c[i]);l=c.join(\",\")}try{return L.apply(n,f.querySelectorAll(l)),n}catch(e){D(t,!0)}finally{s===E&&e.removeAttribute(\"id\")}}}return g(t.replace(V,\"$1\"),e,n,r)}function ue(){var n=[];function r(e,t){return n.push(e+\" \")>w.cacheLength&&delete r[n.shift()],r[e+\" \"]=t}return r}function ce(e){return e[E]=!0,e}function le(e){var t=T.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)w.attrHandle[n[r]]=t}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function pe(t){return function(e){return\"form\"in e?e.parentNode&&!1===e.disabled?\"label\"in e?\"label\"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:\"label\"in e&&e.disabled===t}}function he(a){return ce(function(i){return i=+i,ce(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in p=se.support={},o=se.isXML=function(e){var t=e.namespaceURI,e=(e.ownerDocument||e).documentElement;return!K.test(t||e&&e.nodeName||\"HTML\")},C=se.setDocument=function(e){var t,e=e?e.ownerDocument||e:b;return e!=T&&9===e.nodeType&&e.documentElement&&(a=(T=e).documentElement,k=!o(T),b!=T&&(t=T.defaultView)&&t.top!==t&&(t.addEventListener?t.addEventListener(\"unload\",r,!1):t.attachEvent&&t.attachEvent(\"onunload\",r)),p.scope=le(function(e){return a.appendChild(e).appendChild(T.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),p.attributes=le(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),p.getElementsByTagName=le(function(e){return e.appendChild(T.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),p.getElementsByClassName=ee.test(T.getElementsByClassName),p.getById=le(function(e){return a.appendChild(e).id=E,!T.getElementsByName||!T.getElementsByName(E).length}),p.getById?(w.filter.ID=function(e){var t=e.replace(re,f);return function(e){return e.getAttribute(\"id\")===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&k){e=t.getElementById(e);return e?[e]:[]}}):(w.filter.ID=function(e){var t=e.replace(re,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return e&&e.value===t}},w.find.ID=function(e,t){if(void 0!==t.getElementById&&k){var n,r,o,i=t.getElementById(e);if(i){if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i]}return[]}}),w.find.TAG=p.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):p.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if(\"*\"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},w.find.CLASS=p.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&k)return t.getElementsByClassName(e)},s=[],v=[],(p.qsa=ee.test(T.querySelectorAll))&&(le(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&v.push(\"[*^$]=\"+B+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||v.push(\"\\\\[\"+B+\"*(?:value|\"+I+\")\"),e.querySelectorAll(\"[id~=\"+E+\"-]\").length||v.push(\"~=\"),(t=T.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||v.push(\"\\\\[\"+B+\"*name\"+B+\"*=\"+B+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||v.push(\":checked\"),e.querySelectorAll(\"a#\"+E+\"+*\").length||v.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),v.push(\"[\\\\r\\\\n\\\\f]\")}),le(function(e){e.innerHTML=\"\";var t=T.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&v.push(\"name\"+B+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&v.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&v.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),v.push(\",.*:\")})),(p.matchesSelector=ee.test(l=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&le(function(e){p.disconnectedMatch=l.call(e,\"*\"),l.call(e,\"[s!='']:x\"),s.push(\"!=\",$)}),v=v.length&&new RegExp(v.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),m=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},O=t?function(e,t){if(e===t)return c=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!p.sortDetached&&t.compareDocumentPosition(e)===n?e==T||e.ownerDocument==b&&m(b,e)?-1:t==T||t.ownerDocument==b&&m(b,t)?1:u?R(u,e)-R(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return c=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==T?-1:t==T?1:o?-1:i?1:u?R(u,e)-R(u,t):0;if(o===i)return de(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?de(a[r],s[r]):a[r]==b?-1:s[r]==b?1:0}),T},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(C(e),p.matchesSelector&&k&&!D[t+\" \"]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=l.call(e,t);if(n||p.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){D(t,!0)}return 0\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(re,f),e[3]=(e[3]||e[4]||e[5]||\"\").replace(re,f),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Y.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&G.test(n)&&(t=h(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(re,f).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=_[e+\" \"];return t||(t=new RegExp(\"(^|\"+B+\")\"+e+\"(\"+B+\"|$)\"))&&_(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-1\",\"#\"===e.firstChild.getAttribute(\"href\")})||fe(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),p.attributes&&le(function(e){return e.innerHTML=\"\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||fe(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),le(function(e){return null==e.getAttribute(\"disabled\")})||fe(I,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(C);k.find=p,k.expr=p.selectors,k.expr[\":\"]=k.expr.pseudos,k.uniqueSort=k.unique=p.uniqueSort,k.text=p.getText,k.isXMLDoc=p.isXML,k.contains=p.contains,k.escapeSelector=p.escape;function x(e,t,n){for(var r=[],o=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(o&&k(e).is(n))break;r.push(e)}return r}function E(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var S=k.expr.match.needsContext;function _(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function A(e,n,r){return y(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(k.fn.init=function(e,t,n){if(!e)return this;if(n=n||D,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):y(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:O.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:T,!0)),N.test(r[1])&&k.isPlainObject(t))for(var r in t)y(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=T.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=k.fn,D=k(T);var j=/^(?:parents|prev(?:Until|All))/,q={children:!0,contents:!0,next:!0,prev:!0};function M(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,de=/^$|^module$|\\/(?:java|ecma)script/i;f=T.createDocumentFragment().appendChild(T.createElement(\"div\")),(p=T.createElement(\"input\")).setAttribute(\"type\",\"radio\"),p.setAttribute(\"checked\",\"checked\"),p.setAttribute(\"name\",\"t\"),f.appendChild(p),b.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",b.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",b.option=!!f.lastChild;var pe={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&_(e,t)?k.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var ve=/<|&#?\\w+;/;function me(e,t,n,r,o){for(var i,a,s,u,c,l=t.createDocumentFragment(),f=[],d=0,p=e.length;d\\s*$/g;function Ae(e,t){return _(e,\"table\")&&_(11!==t.nodeType?t:t.firstChild,\"tr\")&&k(e).children(\"tbody\")[0]||e}function De(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function Oe(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function je(e,t){var n,r,o,i;if(1===t.nodeType){if(X.hasData(e)&&(i=X.get(e).events))for(o in X.remove(t,\"handle events\"),i)for(n=0,r=i[o].length;n\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",o=function(e){r.remove(),o=null,e&&t(\"error\"===e.type?404:200,e.type)}),T.head.appendChild(r[0])},abort:function(){o&&o()}}});var Yt=[],Kt=/(=)\\?(?=&|$)|\\?\\?/;k.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Yt.pop()||k.expando+\"_\"+At.guid++;return this[e]=!0,e}}),k.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Kt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Kt.test(e.data)&&\"data\");if(a||\"jsonp\"===e.dataTypes[0])return r=e.jsonpCallback=y(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Kt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(Dt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return i||k.error(r+\" was not called\"),i[0]},e.dataTypes[0]=\"json\",o=C[r],C[r]=function(){i=arguments},n.always(function(){void 0===o?k(C).removeProp(r):C[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Yt.push(r)),i&&y(o)&&o(i[0]),i=o=void 0}),\"script\"}),b.createHTMLDocument=((f=T.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===f.childNodes.length),k.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(b.createHTMLDocument?((r=(t=T.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=T.location.href,t.head.appendChild(r)):t=T),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=me([e],t,r),r&&r.length&&k(r).remove(),k.merge([],n.childNodes)));var r},k.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(\" \");return-1\").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,o,i,a,s=k.css(e,\"position\"),u=k(e),c={};\"static\"===s&&(e.style.position=\"relative\"),i=u.offset(),r=k.css(e,\"top\"),a=k.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(o=(s=u.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),y(t)&&(t=t.call(e,n,k.extend({},i))),null!=t.top&&(c.top=t.top-i.top+o),null!=t.left&&(c.left=t.left-i.left+a),\"using\"in t?t.using.call(e,c):(\"number\"==typeof c.top&&(c.top+=\"px\"),\"number\"==typeof c.left&&(c.left+=\"px\"),u.css(c))}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],o={top:0,left:0};if(\"fixed\"===k.css(r,\"position\"))t=r.getBoundingClientRect();else{for(t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;e&&(e===n.body||e===n.documentElement)&&\"static\"===k.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=k(e).offset()).top+=k.css(e,\"borderTopWidth\",!0),o.left+=k.css(e,\"borderLeftWidth\",!0))}return{top:t.top-o.top-k.css(r,\"marginTop\",!0),left:t.left-o.left-k.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===k.css(e,\"position\");)e=e.offsetParent;return e||re})}}),k.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,o){var i=\"pageYOffset\"===o;k.fn[t]=function(e){return $(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[o]:e[t]:void(r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),k.each([\"top\",\"left\"],function(e,n){k.cssHooks[n]=Ye(b.pixelPosition,function(e,t){if(t)return t=Xe(e,n),Ve.test(t)?k(e).position()[n]+\"px\":t})}),k.each({Height:\"height\",Width:\"width\"},function(a,s){k.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,i){k.fn[i]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),o=r||(!0===e||!0===t?\"margin\":\"border\");return $(this,function(e,t,n){var r;return g(e)?0===i.indexOf(\"outer\")?e[\"inner\"+a]:e.document.documentElement[\"client\"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body[\"scroll\"+a],r[\"scroll\"+a],e.body[\"offset\"+a],r[\"offset\"+a],r[\"client\"+a])):void 0===n?k.css(e,t,o):k.style(e,t,n,o)},s,n?e:void 0,n)}})}),k.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.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(e,n){k.fn[n]=function(e,t){return 0e.length)&&e.substring(0,t.length)===t},vd:function(e,t){if(e===t)return!0;if(11===e.nodeType)return!1;if(t.contains)return t.contains(1!==e.nodeType?e.parentNode:e);if(t.compareDocumentPosition)return 16==(16&t.compareDocumentPosition(e));for(;e&&e!=t;)e=e.parentNode;return!!e},Sb:function(e){return N.a.vd(e,e.ownerDocument.documentElement)},kd:function(e){return!!N.a.Lb(e,N.a.Sb)},R:function(e){return e&&e.tagName&&e.tagName.toLowerCase()},Ac:function(e){return N.onError?function(){try{return e.apply(this,arguments)}catch(e){throw N.onError&&N.onError(e),e}}:e},setTimeout:(c=function(e,t){return setTimeout(N.a.Ac(e),t)},h.toString=function(){return c.toString()},h),Gc:function(e){setTimeout(function(){throw N.onError&&N.onError(e),e},0)},B:function(t,e,n){var r=N.a.Ac(n);if(n=l[e],N.options.useOnlyNativeEvents||n||!Ne)if(n||\"function\"!=typeof t.addEventListener){if(void 0===t.attachEvent)throw Error(\"Browser doesn't support addEventListener or attachEvent\");var o=function(e){r.call(t,e)},i=\"on\"+e;t.attachEvent(i,o),N.a.K.za(t,function(){t.detachEvent(i,o)})}else t.addEventListener(e,r,!1);else u=u||(\"function\"==typeof Ne(t).on?\"on\":\"bind\"),Ne(t)[u](e,r)},Fb:function(e,t){if(!e||!e.nodeType)throw Error(\"element must be a DOM node when calling triggerEvent\");var n=!(\"input\"!==N.a.R(e)||!e.type||\"click\"!=t.toLowerCase())&&(\"checkbox\"==(n=e.type)||\"radio\"==n);if(N.options.useOnlyNativeEvents||!Ne||n)if(\"function\"==typeof Se.createEvent){if(\"function\"!=typeof e.dispatchEvent)throw Error(\"The supplied element doesn't support dispatchEvent\");(n=Se.createEvent(s[t]||\"HTMLEvents\")).initEvent(t,!0,!0,Ee,0,0,0,0,0,!1,!1,!1,!1,0,e),e.dispatchEvent(n)}else if(n&&e.click)e.click();else{if(void 0===e.fireEvent)throw Error(\"Browser doesn't support triggering events\");e.fireEvent(\"on\"+t)}else Ne(e).trigger(t)},f:function(e){return N.O(e)?e():e},bc:function(e){return N.O(e)?e.v():e},Eb:function(t,e,n){var r;e&&(\"object\"===_typeof(t.classList)?(r=t.classList[n?\"add\":\"remove\"],N.a.D(e.match(p),function(e){r.call(t.classList,e)})):\"string\"==typeof t.className.baseVal?o(t.className,\"baseVal\",e,n):o(t,\"className\",e,n))},Bb:function(e,t){var n=N.a.f(t);null!==n&&n!==ke||(n=\"\");t=N.h.firstChild(e);!t||3!=t.nodeType||N.h.nextSibling(t)?N.h.va(e,[e.ownerDocument.createTextNode(n)]):t.data=n,N.a.Ad(e)},Yc:function(e,t){if(e.name=t,d<=7)try{var n=e.name.replace(/[&<>'\"]/g,function(e){return\"&#\"+e.charCodeAt(0)+\";\"});e.mergeAttributes(Se.createElement(\"\"),!1)}catch(e){}},Ad:function(e){9<=d&&((e=1==e.nodeType?e:e.parentNode).style&&(e.style.zoom=e.style.zoom))},wd:function(e){var t;d&&(t=e.style.width,e.style.width=0,e.style.width=t)},Pd:function(e,t){e=N.a.f(e),t=N.a.f(t);for(var n=[],r=e;r<=t;r++)n.push(r);return n},la:function(e){for(var t=[],n=0,r=e.length;n\",\"\"],tbody:e,tfoot:e,tr:[2,\"\",\"
\"],td:e=[3,\"\",\"
\"],th:e,option:e=[1,\"\"],optgroup:e},f=N.a.W<=8,N.a.ua=function(e,t){var n;if(Ne){if(Ne.parseHTML)n=Ne.parseHTML(e,t)||[];else if((n=Ne.clean([e],t))&&n[0]){for(var r=n[0];r.parentNode&&11!==r.parentNode.nodeType;)r=r.parentNode;r.parentNode&&r.parentNode.removeChild(r)}}else{(n=t)||(n=Se);var r=n.parentWindow||n.defaultView||Ee,o=N.a.Db(e).toLowerCase(),i=n.createElement(\"div\"),t=(o=o.match(/^(?:\\x3c!--.*?--\\x3e\\s*?)*?<([a-z]+)[\\s>]/))&&l[o[1]]||u,o=t[0];for(t=\"ignored
\"+t[1]+e+t[2]+\"
\",\"function\"==typeof r.innerShiv?i.appendChild(r.innerShiv(t)):(f&&n.body.appendChild(i),i.innerHTML=t,f&&i.parentNode.removeChild(i));o--;)i=i.lastChild;n=N.a.la(i.lastChild.childNodes)}return n},N.a.Md=function(e,t){t=N.a.ua(e,t);return t.length&&t[0].parentElement||N.a.Yb(t)},N.a.fc=function(e,t){if(N.a.Tb(e),null!==(t=N.a.f(t))&&t!==ke)if(\"string\"!=typeof t&&(t=t.toString()),Ne)Ne(e).html(t);else for(var n=N.a.ua(t,e.ownerDocument),r=0;r]*))?)*\\s+)data-bind\\s*=\\s*([\"'])([\\s\\S]*?)\\3/gi,be=/\\x3c!--\\s*ko\\b\\s*([\\s\\S]*?)\\s*--\\x3e/g,{xd:function(e,t,n){t.isTemplateRewritten(e,n)||t.rewriteTemplate(e,function(e){return N.kc.Ld(e,t)},n)},Ld:function(e,i){return e.replace(me,function(e,t,n,r,o){return Ce(o,t,n,i)}).replace(be,function(e,t){return Ce(t,\"\\x3c!-- ko --\\x3e\",\"#comment\",i)})},md:function(n,r){return N.aa.Xb(function(e,t){e=e.nextSibling;e&&e.nodeName.toLowerCase()===r&&N.ib(e,n,t)})}}),N.b(\"__tr_ambtns\",N.kc.md),function(){N.C={},N.C.F=function(e){var t;(this.F=e)&&(t=N.a.R(e),this.ab=\"script\"===t?1:\"textarea\"===t?2:\"template\"==t&&e.content&&11===e.content.nodeType?3:4)},N.C.F.prototype.text=function(){var e=1===this.ab?\"text\":2===this.ab?\"value\":\"innerHTML\";if(0==arguments.length)return this.F[e];var t=arguments[0];\"innerHTML\"==e?N.a.fc(this.F,t):this.F[e]=t};var t=N.a.g.Z()+\"_\";N.C.F.prototype.data=function(e){if(1===arguments.length)return N.a.g.get(this.F,t+e);N.a.g.set(this.F,t+e,arguments[1])};var o=N.a.g.Z();N.C.F.prototype.nodes=function(){var e=this.F;if(0==arguments.length){var t,n=N.a.g.get(e,o)||{},r=n.lb||(3===this.ab?e.content:4===this.ab?e:ke);return r&&!n.jd||(t=this.text())&&t!==n.bb&&(r=N.a.Md(t,e.ownerDocument),N.a.g.set(e,o,{lb:r,bb:t,jd:!0})),r}n=arguments[0],this.ab!==ke&&this.text(\"\"),N.a.g.set(e,o,{lb:n})},N.C.ia=function(e){this.F=e},N.C.ia.prototype=new N.C.F,N.C.ia.prototype.constructor=N.C.ia,N.C.ia.prototype.text=function(){if(0==arguments.length){var e=N.a.g.get(this.F,o)||{};return e.bb===ke&&e.lb&&(e.bb=e.lb.innerHTML),e.bb}N.a.g.set(this.F,o,{bb:arguments[0]})},N.b(\"templateSources\",N.C),N.b(\"templateSources.domElement\",N.C.F),N.b(\"templateSources.anonymousTemplate\",N.C.ia)}(),function(){function r(e,t,n){var r;for(t=N.h.nextSibling(t);e&&(r=e)!==t;)n(r,e=N.h.nextSibling(r))}function d(e,t){if(e.length){var o=e[0],i=e[e.length-1],n=o.parentNode,a=N.ga.instance,s=a.preprocessNode;if(s){if(r(o,i,function(e,t){var n=e.previousSibling,r=s.call(a,e);r&&(e===o&&(o=r[0]||t),e===i&&(i=r[r.length-1]||n))}),e.length=0,!o)return;o===i?e.push(o):(e.push(o,i),N.a.Ua(e,n))}r(o,i,function(e){1!==e.nodeType&&8!==e.nodeType||N.vc(t,e)}),r(o,i,function(e){1!==e.nodeType&&8!==e.nodeType||N.aa.cd(e,[t])}),N.a.Ua(e,n)}}function u(e){return e.nodeType?e:0\"+t+\"<\\/script>\")},0>10|55296,1023&e|56320))}function r(){T()}var e,d,b,i,o,h,p,g,w,u,l,T,C,a,S,m,s,c,y,E=\"sizzle\"+ +new Date,v=n.document,k=0,x=0,A=ue(),N=ue(),D=ue(),j=ue(),q=function(e,t){return e===t&&(l=!0),0},L={}.hasOwnProperty,t=[],H=t.pop,O=t.push,P=t.push,R=t.slice,M=function(e,t){for(var n=0,r=e.length;n+~]|\"+$+\")\"+$+\"*\"),V=new RegExp($+\"|>\"),G=new RegExp(F),Y=new RegExp(\"^\"+_+\"$\"),Q={ID:new RegExp(\"^#(\"+_+\")\"),CLASS:new RegExp(\"^\\\\.(\"+_+\")\"),TAG:new RegExp(\"^(\"+_+\"|[*])\"),ATTR:new RegExp(\"^\"+W),PSEUDO:new RegExp(\"^\"+F),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+$+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+$+\"*(?:([+-]|)\"+$+\"*(\\\\d+)|))\"+$+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+I+\")$\",\"i\"),needsContext:new RegExp(\"^\"+$+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+$+\"*((?:-\\\\d)?\\\\d*)\"+$+\"*\\\\)|)(?=[^-]|$)\",\"i\")},J=/HTML$/i,K=/^(?:input|select|textarea|button)$/i,Z=/^h\\d$/i,ee=/^[^{]+\\{\\s*\\[native \\w/,te=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ne=/[+~]/,re=new RegExp(\"\\\\\\\\[\\\\da-fA-F]{1,6}\"+$+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),oe=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"�\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},ae=ve(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{P.apply(t=R.call(v.childNodes),v.childNodes),t[v.childNodes.length].nodeType}catch(e){P={apply:t.length?function(e,t){O.apply(e,R.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function se(t,e,n,r){var o,i,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,S)){if(11!==p&&(u=te.exec(t)))if(o=u[1]){if(9===p){if(!(a=e.getElementById(o)))return n;if(a.id===o)return n.push(a),n}else if(f&&(a=f.getElementById(o))&&y(e,a)&&a.id===o)return n.push(a),n}else{if(u[2])return P.apply(n,e.getElementsByTagName(t)),n;if((o=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return P.apply(n,e.getElementsByClassName(o)),n}if(d.qsa&&!j[t+\" \"]&&(!m||!m.test(t))&&(1!==p||\"object\"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(V.test(t)||X.test(t))){for((f=ne.test(t)&&ge(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute(\"id\"))?s=s.replace(oe,ie):e.setAttribute(\"id\",s=E)),i=(l=h(t)).length;i--;)l[i]=(s?\"#\"+s:\":scope\")+\" \"+ye(l[i]);c=l.join(\",\")}try{return P.apply(n,f.querySelectorAll(c)),n}catch(e){j(t,!0)}finally{s===E&&e.removeAttribute(\"id\")}}}return g(t.replace(z,\"$1\"),e,n,r)}function ue(){var n=[];function r(e,t){return n.push(e+\" \")>b.cacheLength&&delete r[n.shift()],r[e+\" \"]=t}return r}function le(e){return e[E]=!0,e}function ce(e){var t=C.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return\"form\"in e?e.parentNode&&!1===e.disabled?\"label\"in e?\"label\"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:\"label\"in e&&e.disabled===t}}function he(a){return le(function(i){return i=+i,le(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in d=se.support={},o=se.isXML=function(e){var t=e.namespaceURI,e=(e.ownerDocument||e).documentElement;return!J.test(t||e&&e.nodeName||\"HTML\")},T=se.setDocument=function(e){var t,e=e?e.ownerDocument||e:v;return e!=C&&9===e.nodeType&&e.documentElement&&(a=(C=e).documentElement,S=!o(C),v!=C&&(t=C.defaultView)&&t.top!==t&&(t.addEventListener?t.addEventListener(\"unload\",r,!1):t.attachEvent&&t.attachEvent(\"onunload\",r)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),d.attributes=ce(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),d.getElementsByClassName=ee.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=E,!C.getElementsByName||!C.getElementsByName(E).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(re,f);return function(e){return e.getAttribute(\"id\")===t}},b.find.ID=function(e,t){if(void 0!==t.getElementById&&S){e=t.getElementById(e);return e?[e]:[]}}):(b.filter.ID=function(e){var t=e.replace(re,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return e&&e.value===t}},b.find.ID=function(e,t){if(void 0!==t.getElementById&&S){var n,r,o,i=t.getElementById(e);if(i){if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if(\"*\"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},b.find.CLASS=d.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&S)return t.getElementsByClassName(e)},s=[],m=[],(d.qsa=ee.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&m.push(\"[*^$]=\"+$+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||m.push(\"\\\\[\"+$+\"*(?:value|\"+I+\")\"),e.querySelectorAll(\"[id~=\"+E+\"-]\").length||m.push(\"~=\"),(t=C.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||m.push(\"\\\\[\"+$+\"*name\"+$+\"*=\"+$+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||m.push(\":checked\"),e.querySelectorAll(\"a#\"+E+\"+*\").length||m.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),m.push(\"[\\\\r\\\\n\\\\f]\")}),ce(function(e){e.innerHTML=\"\";var t=C.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&m.push(\"name\"+$+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&m.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&m.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),m.push(\",.*:\")})),(d.matchesSelector=ee.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,\"*\"),c.call(e,\"[s!='']:x\"),s.push(\"!=\",F)}),m=m.length&&new RegExp(m.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),y=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},q=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==v&&y(v,e)?-1:t==C||t.ownerDocument==v&&y(v,t)?1:u?M(u,e)-M(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==C?-1:t==C?1:o?-1:i?1:u?M(u,e)-M(u,t):0;if(o===i)return pe(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?pe(a[r],s[r]):a[r]==v?-1:s[r]==v?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&S&&!j[t+\" \"]&&(!s||!s.test(t))&&(!m||!m.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){j(t,!0)}return 0\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(re,f),e[3]=(e[3]||e[4]||e[5]||\"\").replace(re,f),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&G.test(n)&&(t=h(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(re,f).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=A[e+\" \"];return t||(t=new RegExp(\"(^|\"+$+\")\"+e+\"(\"+$+\"|$)\"))&&A(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-1\",\"#\"===e.firstChild.getAttribute(\"href\")})||fe(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML=\"\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||fe(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute(\"disabled\")})||fe(I,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(T);S.find=d,S.expr=d.selectors,S.expr[\":\"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;function w(e,t,n){for(var r=[],o=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(o&&S(e).is(n))break;r.push(e)}return r}function E(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function D(e,n,r){return x(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(S.fn.init=function(e,t,n){if(!e)return this;if(n=n||j,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):x(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),N.test(r[1])&&S.isPlainObject(t))for(var r in t)x(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=C.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=S.fn,j=S(C);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,pe=/^$|^module$|\\/(?:java|ecma)script/i;f=C.createDocumentFragment().appendChild(C.createElement(\"div\")),(d=C.createElement(\"input\")).setAttribute(\"type\",\"radio\"),d.setAttribute(\"checked\",\"checked\"),d.setAttribute(\"name\",\"t\"),f.appendChild(d),v.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",v.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",v.option=!!f.lastChild;var de={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&A(e,t)?S.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var me=/<|&#?\\w+;/;function ye(e,t,n,r,o){for(var i,a,s,u,l,c=t.createDocumentFragment(),f=[],p=0,d=e.length;p\\s*$/g;function De(e,t){return A(e,\"table\")&&A(11!==t.nodeType?t:t.firstChild,\"tr\")&&S(e).children(\"tbody\")[0]||e}function je(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function qe(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function Le(e,t){var n,r,o,i;if(1===t.nodeType){if(Y.hasData(e)&&(i=Y.get(e).events))for(o in Y.remove(t,\"handle events\"),i)for(n=0,r=i[o].length;n\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",o=function(e){r.remove(),o=null,e&&t(\"error\"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){o&&o()}}});var Qt=[],Jt=/(=)\\?(?=&|$)|\\?\\?/;S.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Qt.pop()||S.expando+\"_\"+Dt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Jt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Jt.test(e.data)&&\"data\");if(a||\"jsonp\"===e.dataTypes[0])return r=e.jsonpCallback=x(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Jt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(jt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return i||S.error(r+\" was not called\"),i[0]},e.dataTypes[0]=\"json\",o=T[r],T[r]=function(){i=arguments},n.always(function(){void 0===o?S(T).removeProp(r):T[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Qt.push(r)),i&&x(o)&&o(i[0]),i=o=void 0}),\"script\"}),v.createHTMLDocument=((f=C.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===f.childNodes.length),S.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=C.location.href,t.head.appendChild(r)):t=C),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=ye([e],t,r),r&&r.length&&S(r).remove(),S.merge([],n.childNodes)));var r},S.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(\" \");return-1\").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,o,i,a,s=S.css(e,\"position\"),u=S(e),l={};\"static\"===s&&(e.style.position=\"relative\"),i=u.offset(),r=S.css(e,\"top\"),a=S.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(o=(s=u.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),x(t)&&(t=t.call(e,n,S.extend({},i))),null!=t.top&&(l.top=t.top-i.top+o),null!=t.left&&(l.left=t.left-i.left+a),\"using\"in t?t.using.call(e,l):(\"number\"==typeof l.top&&(l.top+=\"px\"),\"number\"==typeof l.left&&(l.left+=\"px\"),u.css(l))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],o={top:0,left:0};if(\"fixed\"===S.css(r,\"position\"))t=r.getBoundingClientRect();else{for(t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;e&&(e===n.body||e===n.documentElement)&&\"static\"===S.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=S(e).offset()).top+=S.css(e,\"borderTopWidth\",!0),o.left+=S.css(e,\"borderLeftWidth\",!0))}return{top:t.top-o.top-S.css(r,\"marginTop\",!0),left:t.left-o.left-S.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===S.css(e,\"position\");)e=e.offsetParent;return e||re})}}),S.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,o){var i=\"pageYOffset\"===o;S.fn[t]=function(e){return F(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[o]:e[t]:void(r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),S.each([\"top\",\"left\"],function(e,n){S.cssHooks[n]=Qe(v.pixelPosition,function(e,t){if(t)return t=Ye(e,n),ze.test(t)?S(e).position()[n]+\"px\":t})}),S.each({Height:\"height\",Width:\"width\"},function(a,s){S.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,i){S.fn[i]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),o=r||(!0===e||!0===t?\"margin\":\"border\");return F(this,function(e,t,n){var r;return g(e)?0===i.indexOf(\"outer\")?e[\"inner\"+a]:e.document.documentElement[\"client\"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body[\"scroll\"+a],r[\"scroll\"+a],e.body[\"offset\"+a],r[\"offset\"+a],r[\"client\"+a])):void 0===n?S.css(e,t,o):S.style(e,t,n,o)},s,n?e:void 0,n)}})}),S.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.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(e,n){S.fn[n]=function(e,t){return 0>10|55296,1023&e|56320))}function r(){T()}var e,d,b,i,o,h,p,g,w,u,l,T,C,a,S,m,s,c,y,E=\"sizzle\"+ +new Date,v=n.document,k=0,x=0,A=ue(),N=ue(),D=ue(),j=ue(),q=function(e,t){return e===t&&(l=!0),0},L={}.hasOwnProperty,t=[],H=t.pop,O=t.push,P=t.push,R=t.slice,M=function(e,t){for(var n=0,r=e.length;n+~]|\"+$+\")\"+$+\"*\"),V=new RegExp($+\"|>\"),G=new RegExp(F),Y=new RegExp(\"^\"+_+\"$\"),Q={ID:new RegExp(\"^#(\"+_+\")\"),CLASS:new RegExp(\"^\\\\.(\"+_+\")\"),TAG:new RegExp(\"^(\"+_+\"|[*])\"),ATTR:new RegExp(\"^\"+W),PSEUDO:new RegExp(\"^\"+F),CHILD:new RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+$+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+$+\"*(?:([+-]|)\"+$+\"*(\\\\d+)|))\"+$+\"*\\\\)|)\",\"i\"),bool:new RegExp(\"^(?:\"+I+\")$\",\"i\"),needsContext:new RegExp(\"^\"+$+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+$+\"*((?:-\\\\d)?\\\\d*)\"+$+\"*\\\\)|)(?=[^-]|$)\",\"i\")},J=/HTML$/i,K=/^(?:input|select|textarea|button)$/i,Z=/^h\\d$/i,ee=/^[^{]+\\{\\s*\\[native \\w/,te=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,ne=/[+~]/,re=new RegExp(\"\\\\\\\\[\\\\da-fA-F]{1,6}\"+$+\"?|\\\\\\\\([^\\\\r\\\\n\\\\f])\",\"g\"),oe=/([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,ie=function(e,t){return t?\"\\0\"===e?\"�\":e.slice(0,-1)+\"\\\\\"+e.charCodeAt(e.length-1).toString(16)+\" \":\"\\\\\"+e},ae=ve(function(e){return!0===e.disabled&&\"fieldset\"===e.nodeName.toLowerCase()},{dir:\"parentNode\",next:\"legend\"});try{P.apply(t=R.call(v.childNodes),v.childNodes),t[v.childNodes.length].nodeType}catch(e){P={apply:t.length?function(e,t){O.apply(e,R.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}function se(t,e,n,r){var o,i,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],\"string\"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,S)){if(11!==p&&(u=te.exec(t)))if(o=u[1]){if(9===p){if(!(a=e.getElementById(o)))return n;if(a.id===o)return n.push(a),n}else if(f&&(a=f.getElementById(o))&&y(e,a)&&a.id===o)return n.push(a),n}else{if(u[2])return P.apply(n,e.getElementsByTagName(t)),n;if((o=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return P.apply(n,e.getElementsByClassName(o)),n}if(d.qsa&&!j[t+\" \"]&&(!m||!m.test(t))&&(1!==p||\"object\"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(V.test(t)||X.test(t))){for((f=ne.test(t)&&ge(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute(\"id\"))?s=s.replace(oe,ie):e.setAttribute(\"id\",s=E)),i=(l=h(t)).length;i--;)l[i]=(s?\"#\"+s:\":scope\")+\" \"+ye(l[i]);c=l.join(\",\")}try{return P.apply(n,f.querySelectorAll(c)),n}catch(e){j(t,!0)}finally{s===E&&e.removeAttribute(\"id\")}}}return g(t.replace(z,\"$1\"),e,n,r)}function ue(){var n=[];function r(e,t){return n.push(e+\" \")>b.cacheLength&&delete r[n.shift()],r[e+\" \"]=t}return r}function le(e){return e[E]=!0,e}function ce(e){var t=C.createElement(\"fieldset\");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){for(var n=e.split(\"|\"),r=n.length;r--;)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return\"form\"in e?e.parentNode&&!1===e.disabled?\"label\"in e?\"label\"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:\"label\"in e&&e.disabled===t}}function he(a){return le(function(i){return i=+i,le(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function ge(e){return e&&void 0!==e.getElementsByTagName&&e}for(e in d=se.support={},o=se.isXML=function(e){var t=e.namespaceURI,e=(e.ownerDocument||e).documentElement;return!J.test(t||e&&e.nodeName||\"HTML\")},T=se.setDocument=function(e){var t,e=e?e.ownerDocument||e:v;return e!=C&&9===e.nodeType&&e.documentElement&&(a=(C=e).documentElement,S=!o(C),v!=C&&(t=C.defaultView)&&t.top!==t&&(t.addEventListener?t.addEventListener(\"unload\",r,!1):t.attachEvent&&t.attachEvent(\"onunload\",r)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement(\"div\")),void 0!==e.querySelectorAll&&!e.querySelectorAll(\":scope fieldset div\").length}),d.attributes=ce(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),d.getElementsByClassName=ee.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=E,!C.getElementsByName||!C.getElementsByName(E).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(re,f);return function(e){return e.getAttribute(\"id\")===t}},b.find.ID=function(e,t){if(void 0!==t.getElementById&&S){e=t.getElementById(e);return e?[e]:[]}}):(b.filter.ID=function(e){var t=e.replace(re,f);return function(e){e=void 0!==e.getAttributeNode&&e.getAttributeNode(\"id\");return e&&e.value===t}},b.find.ID=function(e,t){if(void 0!==t.getElementById&&S){var n,r,o,i=t.getElementById(e);if(i){if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i];for(o=t.getElementsByName(e),r=0;i=o[r++];)if((n=i.getAttributeNode(\"id\"))&&n.value===e)return[i]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if(\"*\"!==e)return i;for(;n=i[o++];)1===n.nodeType&&r.push(n);return r},b.find.CLASS=d.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&S)return t.getElementsByClassName(e)},s=[],m=[],(d.qsa=ee.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML=\"\",e.querySelectorAll(\"[msallowcapture^='']\").length&&m.push(\"[*^$]=\"+$+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\"[selected]\").length||m.push(\"\\\\[\"+$+\"*(?:value|\"+I+\")\"),e.querySelectorAll(\"[id~=\"+E+\"-]\").length||m.push(\"~=\"),(t=C.createElement(\"input\")).setAttribute(\"name\",\"\"),e.appendChild(t),e.querySelectorAll(\"[name='']\").length||m.push(\"\\\\[\"+$+\"*name\"+$+\"*=\"+$+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":checked\").length||m.push(\":checked\"),e.querySelectorAll(\"a#\"+E+\"+*\").length||m.push(\".#.+[+~]\"),e.querySelectorAll(\"\\\\\\f\"),m.push(\"[\\\\r\\\\n\\\\f]\")}),ce(function(e){e.innerHTML=\"\";var t=C.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"name\",\"D\"),e.querySelectorAll(\"[name=d]\").length&&m.push(\"name\"+$+\"*[*^$|!~]?=\"),2!==e.querySelectorAll(\":enabled\").length&&m.push(\":enabled\",\":disabled\"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(\":disabled\").length&&m.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),m.push(\",.*:\")})),(d.matchesSelector=ee.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,\"*\"),c.call(e,\"[s!='']:x\"),s.push(\"!=\",F)}),m=m.length&&new RegExp(m.join(\"|\")),s=s.length&&new RegExp(s.join(\"|\")),t=ee.test(a.compareDocumentPosition),y=t||ee.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,t=t&&t.parentNode;return e===t||!(!t||1!==t.nodeType||!(n.contains?n.contains(t):e.compareDocumentPosition&&16&e.compareDocumentPosition(t)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},q=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==v&&y(v,e)?-1:t==C||t.ownerDocument==v&&y(v,t)?1:u?M(u,e)-M(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],s=[t];if(!o||!i)return e==C?-1:t==C?1:o?-1:i?1:u?M(u,e)-M(u,t):0;if(o===i)return pe(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?pe(a[r],s[r]):a[r]==v?-1:s[r]==v?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&S&&!j[t+\" \"]&&(!s||!s.test(t))&&(!m||!m.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){j(t,!0)}return 0\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(re,f),e[3]=(e[3]||e[4]||e[5]||\"\").replace(re,f),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||\"\":n&&G.test(n)&&(t=h(n,!0))&&(t=n.indexOf(\")\",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(re,f).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=A[e+\" \"];return t||(t=new RegExp(\"(^|\"+$+\")\"+e+\"(\"+$+\"|$)\"))&&A(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute(\"class\")||\"\")})},ATTR:function(t,n,r){return function(e){e=se.attr(e,t);return null==e?\"!=\"===n:!n||(e+=\"\",\"=\"===n?e===r:\"!=\"===n?e!==r:\"^=\"===n?r&&0===e.indexOf(r):\"*=\"===n?r&&-1\",\"#\"===e.firstChild.getAttribute(\"href\")})||fe(\"type|href|height|width\",function(e,t,n){if(!n)return e.getAttribute(t,\"type\"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML=\"\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||fe(\"value\",function(e,t,n){if(!n&&\"input\"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute(\"disabled\")})||fe(I,function(e,t,n){if(!n)return!0===e[t]?t.toLowerCase():(t=e.getAttributeNode(t))&&t.specified?t.value:null}),se}(T);S.find=d,S.expr=d.selectors,S.expr[\":\"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;function w(e,t,n){for(var r=[],o=void 0!==n;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(o&&S(e).is(n))break;r.push(e)}return r}function E(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}var k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i;function D(e,n,r){return x(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):\"string\"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\\w-]+))$/;(S.fn.init=function(e,t,n){if(!e)return this;if(n=n||j,\"string\"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):x(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this);if(!(r=\"<\"===e[0]&&\">\"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return(!t||t.jquery?t||n:this.constructor(t)).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),N.test(r[1])&&S.isPlainObject(t))for(var r in t)x(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(e=C.getElementById(r[2]))&&(this[0]=e,this.length=1),this}).prototype=S.fn,j=S(C);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\\x20\\t\\r\\n\\f]*)/i,pe=/^$|^module$|\\/(?:java|ecma)script/i;f=C.createDocumentFragment().appendChild(C.createElement(\"div\")),(d=C.createElement(\"input\")).setAttribute(\"type\",\"radio\"),d.setAttribute(\"checked\",\"checked\"),d.setAttribute(\"name\",\"t\"),f.appendChild(d),v.checkClone=f.cloneNode(!0).cloneNode(!0).lastChild.checked,f.innerHTML=\"\",v.noCloneChecked=!!f.cloneNode(!0).lastChild.defaultValue,f.innerHTML=\"\",v.option=!!f.lastChild;var de={thead:[1,\"\",\"
\"],col:[2,\"\",\"
\"],tr:[2,\"\",\"
\"],td:[3,\"\",\"
\"],_default:[0,\"\",\"\"]};function he(e,t){var n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||\"*\"):void 0!==e.querySelectorAll?e.querySelectorAll(t||\"*\"):[];return void 0===t||t&&A(e,t)?S.merge([e],n):n}function ge(e,t){for(var n=0,r=e.length;n\",\"\"]);var me=/<|&#?\\w+;/;function ye(e,t,n,r,o){for(var i,a,s,u,l,c=t.createDocumentFragment(),f=[],p=0,d=e.length;p\\s*$/g;function De(e,t){return A(e,\"table\")&&A(11!==t.nodeType?t:t.firstChild,\"tr\")&&S(e).children(\"tbody\")[0]||e}function je(e){return e.type=(null!==e.getAttribute(\"type\"))+\"/\"+e.type,e}function qe(e){return\"true/\"===(e.type||\"\").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute(\"type\"),e}function Le(e,t){var n,r,o,i;if(1===t.nodeType){if(Y.hasData(e)&&(i=Y.get(e).events))for(o in Y.remove(t,\"handle events\"),i)for(n=0,r=i[o].length;n\").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on(\"load error\",o=function(e){r.remove(),o=null,e&&t(\"error\"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){o&&o()}}});var Qt=[],Jt=/(=)\\?(?=&|$)|\\?\\?/;S.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Qt.pop()||S.expando+\"_\"+Dt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter(\"json jsonp\",function(e,t,n){var r,o,i,a=!1!==e.jsonp&&(Jt.test(e.url)?\"url\":\"string\"==typeof e.data&&0===(e.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Jt.test(e.data)&&\"data\");if(a||\"jsonp\"===e.dataTypes[0])return r=e.jsonpCallback=x(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Jt,\"$1\"+r):!1!==e.jsonp&&(e.url+=(jt.test(e.url)?\"&\":\"?\")+e.jsonp+\"=\"+r),e.converters[\"script json\"]=function(){return i||S.error(r+\" was not called\"),i[0]},e.dataTypes[0]=\"json\",o=T[r],T[r]=function(){i=arguments},n.always(function(){void 0===o?S(T).removeProp(r):T[r]=o,e[r]&&(e.jsonpCallback=t.jsonpCallback,Qt.push(r)),i&&x(o)&&o(i[0]),i=o=void 0}),\"script\"}),v.createHTMLDocument=((f=C.implementation.createHTMLDocument(\"\").body).innerHTML=\"
\",2===f.childNodes.length),S.parseHTML=function(e,t,n){return\"string\"!=typeof e?[]:(\"boolean\"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument(\"\")).createElement(\"base\")).href=C.location.href,t.head.appendChild(r)):t=C),r=!n&&[],(n=N.exec(e))?[t.createElement(n[1])]:(n=ye([e],t,r),r&&r.length&&S(r).remove(),S.merge([],n.childNodes)));var r},S.fn.load=function(e,t,n){var r,o,i,a=this,s=e.indexOf(\" \");return-1\").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,i||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,o,i,a,s=S.css(e,\"position\"),u=S(e),l={};\"static\"===s&&(e.style.position=\"relative\"),i=u.offset(),r=S.css(e,\"top\"),a=S.css(e,\"left\"),a=(\"absolute\"===s||\"fixed\"===s)&&-1<(r+a).indexOf(\"auto\")?(o=(s=u.position()).top,s.left):(o=parseFloat(r)||0,parseFloat(a)||0),x(t)&&(t=t.call(e,n,S.extend({},i))),null!=t.top&&(l.top=t.top-i.top+o),null!=t.left&&(l.left=t.left-i.left+a),\"using\"in t?t.using.call(e,l):(\"number\"==typeof l.top&&(l.top+=\"px\"),\"number\"==typeof l.left&&(l.left+=\"px\"),u.css(l))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n=this[0];return n?n.getClientRects().length?(e=n.getBoundingClientRect(),n=n.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],o={top:0,left:0};if(\"fixed\"===S.css(r,\"position\"))t=r.getBoundingClientRect();else{for(t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;e&&(e===n.body||e===n.documentElement)&&\"static\"===S.css(e,\"position\");)e=e.parentNode;e&&e!==r&&1===e.nodeType&&((o=S(e).offset()).top+=S.css(e,\"borderTopWidth\",!0),o.left+=S.css(e,\"borderLeftWidth\",!0))}return{top:t.top-o.top-S.css(r,\"marginTop\",!0),left:t.left-o.left-S.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){for(var e=this.offsetParent;e&&\"static\"===S.css(e,\"position\");)e=e.offsetParent;return e||re})}}),S.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(t,o){var i=\"pageYOffset\"===o;S.fn[t]=function(e){return F(this,function(e,t,n){var r;return g(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n?r?r[o]:e[t]:void(r?r.scrollTo(i?r.pageXOffset:n,i?n:r.pageYOffset):e[t]=n)},t,e,arguments.length)}}),S.each([\"top\",\"left\"],function(e,n){S.cssHooks[n]=Qe(v.pixelPosition,function(e,t){if(t)return t=Ye(e,n),ze.test(t)?S(e).position()[n]+\"px\":t})}),S.each({Height:\"height\",Width:\"width\"},function(a,s){S.each({padding:\"inner\"+a,content:s,\"\":\"outer\"+a},function(r,i){S.fn[i]=function(e,t){var n=arguments.length&&(r||\"boolean\"!=typeof e),o=r||(!0===e||!0===t?\"margin\":\"border\");return F(this,function(e,t,n){var r;return g(e)?0===i.indexOf(\"outer\")?e[\"inner\"+a]:e.document.documentElement[\"client\"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body[\"scroll\"+a],r[\"scroll\"+a],e.body[\"offset\"+a],r[\"offset\"+a],r[\"client\"+a])):void 0===n?S.css(e,t,o):S.style(e,t,n,o)},s,n?e:void 0,n)}})}),S.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.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(e,n){S.fn[n]=function(e,t){return 0